[All] Basic Accessibility Support (#713)
authorSamantha Houts <samantha@teamredwall.com>
Tue, 31 Jan 2017 19:49:15 +0000 (11:49 -0800)
committerKangho Hur <kangho.hur@samsung.com>
Fri, 24 Mar 2017 04:16:43 +0000 (13:16 +0900)
* [Core] Add accessibility properties

* [Controls] Add accessibility gallery

* [iOS] Implement accessibility properties

* [Android] Implement accessibilty properties

* [Win] Implement accessibility properties

* [Win] Select ListView item on selected for a11y

* Update docs

* TODO: macOS accessibility

* [iOS] Fix failing UI Tests

30 files changed:
Xamarin.Forms.Controls/ControlGalleryPages/AccessibilityGallery.cs [new file with mode: 0644]
Xamarin.Forms.Controls/CoreGallery.cs
Xamarin.Forms.Controls/Xamarin.Forms.Controls.csproj
Xamarin.Forms.Core.Windows.UITests/Xamarin.Forms.Core.Windows.UITests.csproj
Xamarin.Forms.Core/Accessibility.cs [new file with mode: 0644]
Xamarin.Forms.Core/Xamarin.Forms.Core.csproj
Xamarin.Forms.Platform.Android/AppCompat/FrameRenderer.cs
Xamarin.Forms.Platform.Android/AppCompat/MasterDetailPageRenderer.cs
Xamarin.Forms.Platform.Android/IVisualElementRenderer.cs
Xamarin.Forms.Platform.Android/Renderers/MasterDetailRenderer.cs
Xamarin.Forms.Platform.Android/Renderers/ScrollViewRenderer.cs
Xamarin.Forms.Platform.Android/ViewRenderer.cs
Xamarin.Forms.Platform.Android/VisualElementExtensions.cs
Xamarin.Forms.Platform.Android/VisualElementRenderer.cs
Xamarin.Forms.Platform.UAP/MasterDetailPageRenderer.cs
Xamarin.Forms.Platform.UAP/TabbedPageRenderer.cs
Xamarin.Forms.Platform.WinRT.Phone/TabbedPageRenderer.cs
Xamarin.Forms.Platform.WinRT.Tablet/TabbedPageRenderer.cs
Xamarin.Forms.Platform.WinRT/CarouselPageRenderer.cs
Xamarin.Forms.Platform.WinRT/IVisualElementRenderer.cs
Xamarin.Forms.Platform.WinRT/ListViewRenderer.cs
Xamarin.Forms.Platform.WinRT/MasterDetailPageRenderer.cs
Xamarin.Forms.Platform.WinRT/NavigationPageRenderer.cs
Xamarin.Forms.Platform.WinRT/ViewRenderer.cs
Xamarin.Forms.Platform.WinRT/VisualElementRenderer.cs
Xamarin.Forms.Platform.iOS/Renderers/ButtonRenderer.cs
Xamarin.Forms.Platform.iOS/Renderers/LabelRenderer.cs
Xamarin.Forms.Platform.iOS/ViewRenderer.cs
Xamarin.Forms.Platform.iOS/VisualElementRenderer.cs
docs/Xamarin.Forms.Core/Xamarin.Forms/Accessibility.xml [new file with mode: 0644]

diff --git a/Xamarin.Forms.Controls/ControlGalleryPages/AccessibilityGallery.cs b/Xamarin.Forms.Controls/ControlGalleryPages/AccessibilityGallery.cs
new file mode 100644 (file)
index 0000000..e235415
--- /dev/null
@@ -0,0 +1,145 @@
+
+namespace Xamarin.Forms.Controls
+{
+       public class AccessibilityGallery : ContentPage
+       {
+               public AccessibilityGallery()
+               {
+                       // https://developer.xamarin.com/guides/android/advanced_topics/accessibility/
+                       // https://developer.xamarin.com/guides/ios/advanced_topics/accessibility/
+                       // https://msdn.microsoft.com/en-us/windows/uwp/accessibility/basic-accessibility-information
+
+                       string screenReader = "";
+                       string scrollFingers = "";
+                       string explore = "";
+
+                       switch (Device.RuntimePlatform)
+                       {
+                               case Device.iOS:
+                                       screenReader = "VoiceOver";
+                                       scrollFingers = "three fingers";
+                                       explore = "Use two fingers to swipe up or down the screen to read all of the elements on this page.";
+                                       break;
+                               case Device.Android:
+                                       screenReader = "TalkBack";
+                                       scrollFingers = "two fingers";
+                                       explore = "Drag one finger across the screen to read each element on the page.";
+                                       break;
+                               case Device.Windows:
+                               case Device.WinPhone:
+                                       screenReader = "Narrator";
+                                       scrollFingers = "two fingers";
+                                       break;
+                               default:
+                                       screenReader = "the native screen reader";
+                                       break;
+                       }
+
+                       var instructions = new Label { Text = $"Please enable {screenReader}. {explore} Use {scrollFingers} to scroll the view. Tap an element once to hear the description. Double tap anywhere on the screen to activate the selected element. Swipe left or right with one finger to switch to the previous or next element." };
+
+                       const string EntryPlaceholder = "Your name";
+                       const string EntryHint = "Type your name.";
+
+                       var instructions2 = new Label { Text = $"The following Entry should read aloud \"{EntryPlaceholder}. {EntryHint}\", plus native instructions on how to use an entry element. Note that Android will NOT read the Hint if a Placeholder is provided." };
+                       var entry = new Entry { Placeholder = EntryPlaceholder };
+                       entry.SetAccessibilityHint(EntryHint);
+
+
+                       var activityIndicator = new ActivityIndicator();
+                       activityIndicator.SetAccessibilityName("Progress indicator");
+
+
+                       const string ButtonText = "Update progress";
+                       var instructions3 = new Label { Text = $"The following Button should read aloud \"{ButtonText}\", plus native instructions on how to use a button." };
+                       var button = new Button { Text = ButtonText };
+                       button.Clicked += (sender, e) =>
+                       {
+                               activityIndicator.IsRunning = !activityIndicator.IsRunning;
+                               activityIndicator.SetAccessibilityHint(activityIndicator.IsRunning ? "Running." : "Not running");
+                       };
+
+
+                       const string ImageHint = "Tap to show an alert.";
+                       var instructions4 = new Label { Text = $"The following Image should read aloud \"{ImageHint}\". You should be able to tap the image and hear an alert box." };
+                       var image = new Image { Source = "photo.jpg" };
+                       image.GestureRecognizers.Add(new TapGestureRecognizer { Command = new Command(() => DisplayAlert("Success", "You tapped the image", "OK")) });
+                       image.SetAccessibilityHint(ImageHint);
+                       // images are ignored by default on iOS (at least, Forms images are); 
+                       // make accessible in order to enable the gesture and narration
+                       image.SetIsInAccessibleTree(true);
+
+
+                       var instructions5 = new Label { Text = $"The following Button should NOT be read aloud, nor should you be able to interact with it while {screenReader} is active." };
+                       var button2 = new Button { Text = "I am not accessible" };
+                       // setting this to false seems to have no effect on any platform
+                       button2.SetIsInAccessibleTree(false);
+
+
+                       var boxView = new BoxView { Color = Color.Purple };
+                       boxView.GestureRecognizers.Add(new TapGestureRecognizer { Command = new Command(() => DisplayAlert("Success", "You tapped the box", "OK")) });
+                       boxView.SetAccessibilityName("Box");
+                       boxView.SetAccessibilityHint("Shows a purple box.");
+                       //boxView.SetIsInAccessibleTree(true);
+
+                       var stack = new StackLayout
+                       {
+                               Children =
+                               {
+                                       instructions,
+                                       instructions2,
+                                       entry,
+                                       instructions3,
+                                       button,
+                                       activityIndicator,
+                                       instructions4,
+                                       image,
+                                       instructions5,
+                                       button2,
+                                       boxView
+                               }
+                       };
+
+                       var scrollView = new ScrollView { Content = stack };
+
+                       // TODO: Test Pan/Pinch gestures
+                       // TODO: Test CarouselView
+
+                       Content = scrollView;
+               }
+
+       }
+
+
+       public static class AccessibilityExtensions
+       {
+               public static void SetAccessibilityName(this VisualElement element, string name)
+               {
+                       element.SetValue(Accessibility.NameProperty, name);
+               }
+
+               public static string GetAccessibilityName(this VisualElement element)
+               {
+                       return (string)element.GetValue(Accessibility.NameProperty);
+               }
+
+               public static void SetAccessibilityHint(this VisualElement element, string hint)
+               {
+                       element.SetValue(Accessibility.HintProperty, hint);
+               }
+
+               public static string GetAccessibilityHint(this VisualElement element)
+               {
+                       return (string)element.GetValue(Accessibility.HintProperty);
+               }
+
+               public static void SetIsInAccessibleTree(this VisualElement element, bool value)
+               {
+                       element.SetValue(Accessibility.IsInAccessibleTreeProperty, value);
+               }
+
+               public static bool GetIsInAccessibleTree(this VisualElement element)
+               {
+                       return (bool)element.GetValue(Accessibility.IsInAccessibleTreeProperty);
+               }
+       }
+}
index 83d8ec6..924d412 100644 (file)
@@ -212,6 +212,7 @@ namespace Xamarin.Forms.Controls
                                }               
                        };
 #endif
+                       SetValue(Accessibility.NameProperty, "SwapRoot");
                }
        }
 
@@ -235,9 +236,16 @@ namespace Xamarin.Forms.Controls
 
                        public Func<Page> Realize { get; set; }
                        public string Title { get; set; }
+
+                       public override string ToString()
+                       {       
+                               // a11y: let Narrator read a friendly string instead of the default ToString()
+                               return Title;
+                       }
                }
 
                List<GalleryPageFactory> _pages = new List<GalleryPageFactory> {
+                               new GalleryPageFactory(() => new AccessibilityGallery(), "Accessibility"),
                                new GalleryPageFactory(() => new PlatformSpecificsGallery(), "Platform Specifics"),
                                new GalleryPageFactory(() => new NativeBindingGalleryPage(), "Native Binding Controls Gallery"),
                                new GalleryPageFactory(() => new XamlNativeViews(), "Xaml Native Views Gallery"),
@@ -368,6 +376,8 @@ namespace Xamarin.Forms.Controls
 
                                SelectedItem = null;
                        };
+
+                       SetValue(Accessibility.NameProperty, "Core Pages");
                }
 
                NavigationBehavior navigationBehavior;
index fa6da67..717f31e 100644 (file)
 <?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>
-               <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
-               <NoWarn>0114;0108;0109;4014;0649;0169;0472;0414;0168;0219;0429</NoWarn>
-       </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>
-               <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
-               <NoWarn>0114;0108;0109;4014;0649;0169;0472;0414;0168;0219;0429</NoWarn>
-       </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>
-               <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
-               <NoWarn>0114;0108;0109;4014;0649;0169;0472;0414;0168;0219;0429</NoWarn>
-       </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.Pages\Xamarin.Forms.Pages.csproj">
-                       <Project>{d6133dbd-6c60-4bd5-bea2-07e0a3927c31}</Project>
-                       <Name>Xamarin.Forms.Pages</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="AppLifeCycle.cs" />
-               <Compile Include="Bugzilla44596SplashPage.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\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="GalleryPages\PlatformSpecificsGalleries\ApplicationAndroid.cs" />
-               <Compile Include="GalleryPages\PlatformSpecificsGalleries\EntryPageiOS.cs" />
-               <Compile Include="GalleryPages\PlatformSpecificsGalleries\MasterDetailPageiOS.cs" />
-               <Compile Include="GalleryPages\PlatformSpecificsGalleries\MasterDetailPageWindows.cs" />
-               <Compile Include="GalleryPages\PlatformSpecificsGalleries\NavigationPageiOS.cs" />
-               <Compile Include="GalleryPages\PlatformSpecificsGalleries\NavigationPageWindows.cs" />
-               <Compile Include="GalleryPages\PlatformSpecificsGalleries\TabbedPageAndroid.cs" />
-               <Compile Include="GalleryPages\PlatformSpecificsGalleries\TabbedPageiOS.cs" />
-               <Compile Include="GalleryPages\PlatformSpecificsGalleries\TabbedPageWindows.cs" />
-               <Compile Include="GalleryPages\PlatformSpecificsGalleries\VisualElementiOS.cs" />
-               <Compile Include="GalleryPages\PlatformSpecificsGalleries\WindowsPlatformSpecificsGalleryHelpers.cs" />
-               <Compile Include="GalleryPages\PlatformSpecificsGallery.cs" />
-               <Compile Include="LegacyRepro\Page1.xaml.cs">
-                       <DependentUpon>Page1.xaml</DependentUpon>
-               </Compile>
-               <Compile Include="MainPageLifeCycleTests.cs" />
-               <Compile Include="NavReproApp.cs" />
-               <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="SimpleApp.cs" />
-               <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\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" />
-               <Compile Include="GalleryPages\AppLinkPageGallery.cs" />
-               <Compile Include="ControlGalleryPages\NativeBindingGalleryPage.cs" />
-               <Compile Include="GalleryPages\XamlNativeViews.xaml.cs">
-                       <DependentUpon>XamlNativeViews.xaml</DependentUpon>
-               </Compile>
-               <Compile Include="HanselForms\BaseView.cs" />
-               <Compile Include="HanselForms\HBaseViewModel.cs" />
-               <Compile Include="HanselForms\RootPage.cs" />
-               <Compile Include="HanselForms\WebsiteView.cs" />
-               <Compile Include="HanselForms\BlogPage.xaml.cs">
-                       <DependentUpon>BlogPage.xaml</DependentUpon>
-               </Compile>
-               <Compile Include="HanselForms\MyAbout.xaml.cs">
-                       <DependentUpon>MyAbout.xaml</DependentUpon>
-               </Compile>
-               <Compile Include="HanselForms\TwitterPage.xaml.cs">
-                       <DependentUpon>TwitterPage.xaml</DependentUpon>
-               </Compile>
-               <Compile Include="GalleryPages\MacTwitterDemo.xaml.cs">
-                       <DependentUpon>MacTwitterDemo.xaml</DependentUpon>
-               </Compile>
-       </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.
+  <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>
+    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+    <NoWarn>0114;0108;0109;4014;0649;0169;0472;0414;0168;0219;0429</NoWarn>
+  </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>
+    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+    <NoWarn>0114;0108;0109;4014;0649;0169;0472;0414;0168;0219;0429</NoWarn>
+  </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>
+    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+    <NoWarn>0114;0108;0109;4014;0649;0169;0472;0414;0168;0219;0429</NoWarn>
+  </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.Pages\Xamarin.Forms.Pages.csproj">
+      <Project>{d6133dbd-6c60-4bd5-bea2-07e0a3927c31}</Project>
+      <Name>Xamarin.Forms.Pages</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="AppLifeCycle.cs" />
+    <Compile Include="Bugzilla44596SplashPage.cs" />
+    <Compile Include="ControlGalleryPages\AccessibilityGallery.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\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="GalleryPages\PlatformSpecificsGalleries\ApplicationAndroid.cs" />
+    <Compile Include="GalleryPages\PlatformSpecificsGalleries\EntryPageiOS.cs" />
+    <Compile Include="GalleryPages\PlatformSpecificsGalleries\MasterDetailPageiOS.cs" />
+    <Compile Include="GalleryPages\PlatformSpecificsGalleries\MasterDetailPageWindows.cs" />
+    <Compile Include="GalleryPages\PlatformSpecificsGalleries\NavigationPageiOS.cs" />
+    <Compile Include="GalleryPages\PlatformSpecificsGalleries\NavigationPageWindows.cs" />
+    <Compile Include="GalleryPages\PlatformSpecificsGalleries\TabbedPageAndroid.cs" />
+    <Compile Include="GalleryPages\PlatformSpecificsGalleries\TabbedPageiOS.cs" />
+    <Compile Include="GalleryPages\PlatformSpecificsGalleries\TabbedPageWindows.cs" />
+    <Compile Include="GalleryPages\PlatformSpecificsGalleries\VisualElementiOS.cs" />
+    <Compile Include="GalleryPages\PlatformSpecificsGalleries\WindowsPlatformSpecificsGalleryHelpers.cs" />
+    <Compile Include="GalleryPages\PlatformSpecificsGallery.cs" />
+    <Compile Include="LegacyRepro\Page1.xaml.cs">
+      <DependentUpon>Page1.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="MainPageLifeCycleTests.cs" />
+    <Compile Include="NavReproApp.cs" />
+    <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="SimpleApp.cs" />
+    <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\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" />
+    <Compile Include="GalleryPages\AppLinkPageGallery.cs" />
+    <Compile Include="ControlGalleryPages\NativeBindingGalleryPage.cs" />
+    <Compile Include="GalleryPages\XamlNativeViews.xaml.cs">
+      <DependentUpon>XamlNativeViews.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="HanselForms\BaseView.cs" />
+    <Compile Include="HanselForms\HBaseViewModel.cs" />
+    <Compile Include="HanselForms\RootPage.cs" />
+    <Compile Include="HanselForms\WebsiteView.cs" />
+    <Compile Include="HanselForms\BlogPage.xaml.cs">
+      <DependentUpon>BlogPage.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="HanselForms\MyAbout.xaml.cs">
+      <DependentUpon>MyAbout.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="HanselForms\TwitterPage.xaml.cs">
+      <DependentUpon>TwitterPage.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="GalleryPages\MacTwitterDemo.xaml.cs">
+      <DependentUpon>MacTwitterDemo.xaml</DependentUpon>
+    </Compile>
+  </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>
-               <EmbeddedResource Include="GalleryPages\XamlNativeViews.xaml">
-                       <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
-               </EmbeddedResource>
-               <EmbeddedResource Include="GalleryPages\MacTwitterDemo.xaml">
-                       <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
-               </EmbeddedResource>
-               <EmbeddedResource Include="HanselForms\MyAbout.xaml">
-                       <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
-               </EmbeddedResource>
-               <EmbeddedResource Include="HanselForms\BlogPage.xaml">
-                       <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
-               </EmbeddedResource>
-               <EmbeddedResource Include="HanselForms\TwitterPage.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'))" />
-       </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>
-               <None Include="app.config" />
-               <EmbeddedResource Include="controlgallery.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>
-               <Reference Include="PCLStorage, Version=1.0.2.0, Culture=neutral, PublicKeyToken=286fe515a2c35b64, processorArchitecture=MSIL">
-                       <HintPath>..\packages\PCLStorage.1.0.2\lib\portable-net45+wp8+wpa81+win8+monoandroid+monotouch+Xamarin.iOS+Xamarin.Mac\PCLStorage.dll</HintPath>
-                       <Private>True</Private>
-               </Reference>
-               <Reference Include="PCLStorage.Abstractions, Version=1.0.2.0, Culture=neutral, PublicKeyToken=286fe515a2c35b64, processorArchitecture=MSIL">
-                       <HintPath>..\packages\PCLStorage.1.0.2\lib\portable-net45+wp8+wpa81+win8+monoandroid+monotouch+Xamarin.iOS+Xamarin.Mac\PCLStorage.Abstractions.dll</HintPath>
-                       <Private>True</Private>
-               </Reference>
-               <Reference Include="Xamarin.Insights">
-                       <HintPath>..\packages\Xamarin.Insights.1.12.3\lib\portable-win+net45+wp80+windows8+wpa+MonoAndroid10+MonoTouch10\Xamarin.Insights.dll</HintPath>
-               </Reference>
-               <Reference Include="System.Net.Http">
-                       <HintPath>..\packages\Microsoft.Net.Http.2.2.29\lib\portable-net40+sl4+win8+wp71+wpa81\System.Net.Http.dll</HintPath>
-               </Reference>
-               <Reference Include="System.Net.Http.Extensions">
-                       <HintPath>..\packages\Microsoft.Net.Http.2.2.29\lib\portable-net40+sl4+win8+wp71+wpa81\System.Net.Http.Extensions.dll</HintPath>
-               </Reference>
-               <Reference Include="System.Net.Http.Primitives">
-                       <HintPath>..\packages\Microsoft.Net.Http.2.2.29\lib\portable-net40+sl4+win8+wp71+wpa81\System.Net.Http.Primitives.dll</HintPath>
-               </Reference>
-       </ItemGroup>
-       <Target Name="BeforeBuild">
-               <CreateItem Include="blank.config">
-                       <Output TaskParameter="Include" ItemName="ConfigFile" />
-               </CreateItem>
-               <Copy SourceFiles="@(ConfigFile)" DestinationFiles="controlgallery.config" Condition="!Exists('controlgallery.config')" />
-       </Target>
-       <Import Project="..\packages\Xamarin.Insights.1.12.3\build\portable-win+net45+wp80+windows8+wpa+MonoAndroid10+MonoTouch10\Xamarin.Insights.targets" Condition="Exists('..\packages\Xamarin.Insights.1.12.3\build\portable-win+net45+wp80+windows8+wpa+MonoAndroid10+MonoTouch10\Xamarin.Insights.targets')" />
+  <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>
+    <EmbeddedResource Include="GalleryPages\XamlNativeViews.xaml">
+      <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+    </EmbeddedResource>
+    <EmbeddedResource Include="GalleryPages\MacTwitterDemo.xaml">
+      <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+    </EmbeddedResource>
+    <EmbeddedResource Include="HanselForms\MyAbout.xaml">
+      <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+    </EmbeddedResource>
+    <EmbeddedResource Include="HanselForms\BlogPage.xaml">
+      <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+    </EmbeddedResource>
+    <EmbeddedResource Include="HanselForms\TwitterPage.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'))" />
+  </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>
+    <None Include="app.config" />
+    <EmbeddedResource Include="controlgallery.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>
+    <Reference Include="PCLStorage, Version=1.0.2.0, Culture=neutral, PublicKeyToken=286fe515a2c35b64, processorArchitecture=MSIL">
+      <HintPath>..\packages\PCLStorage.1.0.2\lib\portable-net45+wp8+wpa81+win8+monoandroid+monotouch+Xamarin.iOS+Xamarin.Mac\PCLStorage.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="PCLStorage.Abstractions, Version=1.0.2.0, Culture=neutral, PublicKeyToken=286fe515a2c35b64, processorArchitecture=MSIL">
+      <HintPath>..\packages\PCLStorage.1.0.2\lib\portable-net45+wp8+wpa81+win8+monoandroid+monotouch+Xamarin.iOS+Xamarin.Mac\PCLStorage.Abstractions.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="Xamarin.Insights">
+      <HintPath>..\packages\Xamarin.Insights.1.12.3\lib\portable-win+net45+wp80+windows8+wpa+MonoAndroid10+MonoTouch10\Xamarin.Insights.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Net.Http">
+      <HintPath>..\packages\Microsoft.Net.Http.2.2.29\lib\portable-net40+sl4+win8+wp71+wpa81\System.Net.Http.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Net.Http.Extensions">
+      <HintPath>..\packages\Microsoft.Net.Http.2.2.29\lib\portable-net40+sl4+win8+wp71+wpa81\System.Net.Http.Extensions.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Net.Http.Primitives">
+      <HintPath>..\packages\Microsoft.Net.Http.2.2.29\lib\portable-net40+sl4+win8+wp71+wpa81\System.Net.Http.Primitives.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+  <Target Name="BeforeBuild">
+    <CreateItem Include="blank.config">
+      <Output TaskParameter="Include" ItemName="ConfigFile" />
+    </CreateItem>
+    <Copy SourceFiles="@(ConfigFile)" DestinationFiles="controlgallery.config" Condition="!Exists('controlgallery.config')" />
+  </Target>
+  <Import Project="..\packages\Xamarin.Insights.1.12.3\build\portable-win+net45+wp80+windows8+wpa+MonoAndroid10+MonoTouch10\Xamarin.Insights.targets" Condition="Exists('..\packages\Xamarin.Insights.1.12.3\build\portable-win+net45+wp80+windows8+wpa+MonoAndroid10+MonoTouch10\Xamarin.Insights.targets')" />
 </Project>
\ No newline at end of file
index 0758b8b..f297b07 100644 (file)
       <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" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
diff --git a/Xamarin.Forms.Core/Accessibility.cs b/Xamarin.Forms.Core/Accessibility.cs
new file mode 100644 (file)
index 0000000..e866d31
--- /dev/null
@@ -0,0 +1,14 @@
+
+namespace Xamarin.Forms
+{
+       public class Accessibility
+       {
+               public static readonly BindableProperty HintProperty = BindableProperty.Create("Hint", typeof(string), typeof(Element), default(string));
+
+               public static readonly BindableProperty IsInAccessibleTreeProperty = BindableProperty.Create("IsInAccessibleTree", typeof(bool?), typeof(Element), null);
+
+               public static readonly BindableProperty LabeledByProperty = BindableProperty.Create("LabeledBy", typeof(VisualElement), typeof(Element), default(VisualElement));
+
+               public static readonly BindableProperty NameProperty = BindableProperty.Create("Name", typeof(string), typeof(Element), default(string));
+       }
+}
index 6b978ac..f1b7f6f 100644 (file)
@@ -50,6 +50,7 @@
   </PropertyGroup>
   <ItemGroup>
     <Compile Include="AbsoluteLayoutFlags.cs" />
+    <Compile Include="Accessibility.cs" />
     <Compile Include="ActionSheetArguments.cs" />
     <Compile Include="AlertArguments.cs" />
     <Compile Include="AnimatableKey.cs" />
index 2b657b5..7c40ea8 100644 (file)
@@ -21,6 +21,7 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
 
                float _defaultElevation = -1f;
                float _defaultCornerRadius = -1f;
+               int? _defaultLabelFor;
 
                bool _clickable;
                bool _disposed;
@@ -113,6 +114,14 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
                                ContentDescription = Element.AutomationId;
                }
 
+               void IVisualElementRenderer.SetLabelFor(int? id)
+               {
+                       if (_defaultLabelFor == null)
+                               _defaultLabelFor = LabelFor;
+
+                       LabelFor = (int)(id ?? _defaultLabelFor);
+               }
+
                VisualElementTracker IVisualElementRenderer.Tracker => _visualElementTracker;
 
                void IVisualElementRenderer.UpdateLayout()
index 757a98b..85ab6b7 100644 (file)
@@ -165,6 +165,10 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
                                _tracker = new VisualElementTracker(this);
                }
 
+               void IVisualElementRenderer.SetLabelFor(int? id)
+               {
+               }
+
                VisualElementTracker IVisualElementRenderer.Tracker => _tracker;
 
                void IVisualElementRenderer.UpdateLayout()
index 9939351..da565ce 100644 (file)
@@ -17,6 +17,9 @@ namespace Xamarin.Forms.Platform.Android
                SizeRequest GetDesiredSize(int widthConstraint, int heightConstraint);
 
                void SetElement(VisualElement element);
+
+               void SetLabelFor(int? id);
+
                void UpdateLayout();
        }
 }
\ No newline at end of file
index ec9c620..d18781a 100644 (file)
@@ -287,6 +287,10 @@ namespace Xamarin.Forms.Platform.Android
                        SetDrawerLockMode(_page.IsGestureEnabled ? LockModeUnlocked : LockModeLockedClosed);
                }
 
+               void IVisualElementRenderer.SetLabelFor(int? id)
+               {
+               }
+
                void SetLockMode(int lockMode)
                {
                        if (_currentLockMode != lockMode)
index 6db51c2..a2e3ddb 100644 (file)
@@ -328,6 +328,10 @@ namespace Xamarin.Forms.Platform.Android
                        }
                }
 
+               void IVisualElementRenderer.SetLabelFor(int? id)
+               {
+               }
+
                void UpdateBackgroundColor()
                {
                        SetBackgroundColor(Element.BackgroundColor.ToAndroid(Color.Transparent));
index c4bd3fa..31a9c28 100644 (file)
@@ -19,6 +19,9 @@ namespace Xamarin.Forms.Platform.Android
                }
 
                ViewGroup _container;
+               string _defaultContentDescription;
+               bool? _defaultFocusable;
+               string _defaultHint;
 
                bool _disposed;
                EventHandler<VisualElement.FocusRequestArgs> _focusChangeHandler;
@@ -66,7 +69,7 @@ namespace Xamarin.Forms.Platform.Android
                {
                        if (Control == null)
                                return (base.GetDesiredSize(widthConstraint, heightConstraint));
-                                       
+
                        AView view = _container == this ? (AView)Control : _container;
                        view.Measure(widthConstraint, heightConstraint);
 
@@ -124,6 +127,8 @@ namespace Xamarin.Forms.Platform.Android
 
                        if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
                                UpdateIsEnabled();
+                       else if (e.PropertyName == Accessibility.LabeledByProperty.PropertyName)
+                               SetLabeledBy();
                }
 
                protected override void OnLayout(bool changed, int l, int t, int r, int b)
@@ -155,6 +160,79 @@ namespace Xamarin.Forms.Platform.Android
                        }
                }
 
+               protected override void SetContentDescription()
+               {
+                       if (Control == null)
+                       {
+                               base.SetContentDescription();
+                               return;
+                       }
+
+                       if (Element == null)
+                               return;
+
+                       if (SetHint())
+                               return;
+
+                       if (_defaultContentDescription == null)
+                               _defaultContentDescription = Control.ContentDescription;
+
+                       var elemValue = string.Join(" ", (string)Element.GetValue(Accessibility.NameProperty), (string)Element.GetValue(Accessibility.HintProperty));
+
+                       if (!string.IsNullOrWhiteSpace(elemValue))
+                               Control.ContentDescription = elemValue;
+                       else
+                               Control.ContentDescription = _defaultContentDescription;
+               }
+
+               protected override void SetFocusable()
+               {
+                       if (Control == null)
+                       {
+                               base.SetFocusable();
+                               return;
+                       }
+
+                       if (Element == null)
+                               return;
+
+                       if (!_defaultFocusable.HasValue)
+                               _defaultFocusable = Control.Focusable;
+
+                       Control.Focusable = (bool)((bool?)Element.GetValue(Accessibility.IsInAccessibleTreeProperty) ?? _defaultFocusable);
+               }
+
+               protected override bool SetHint()
+               {                               
+                       if (Control == null)
+                       {
+                               return base.SetHint();
+                       }
+
+                       if (Element == null)
+                               return false;
+
+                       var textView = Control as global::Android.Widget.TextView;
+                       if (textView == null)
+                               return false;
+
+                       // Let the specified Title/Placeholder take precedence, but don't set the ContentDescription (won't work anyway)
+                       if (((Element as Picker)?.Title ?? (Element as Entry)?.Placeholder ?? (Element as EntryCell)?.Placeholder) != null)
+                               return true;
+
+                       if (_defaultHint == null)
+                               _defaultHint = textView.Hint;
+
+                       var elemValue = string.Join(". ", (string)Element.GetValue(Accessibility.NameProperty), (string)Element.GetValue(Accessibility.HintProperty));
+
+                       if (!string.IsNullOrWhiteSpace(elemValue))
+                               textView.Hint = elemValue;
+                       else
+                               textView.Hint = _defaultHint;
+
+                       return true;
+               }
+
                protected void SetNativeControl(TNativeView control)
                {
                        SetNativeControl(control, this);
@@ -219,6 +297,25 @@ namespace Xamarin.Forms.Platform.Android
                        Control.OnFocusChangeListener = this;
 
                        UpdateIsEnabled();
+                       SetLabeledBy();
+               }
+
+               void SetLabeledBy()
+               {
+                       if (Element == null || Control == null)
+                               return;
+
+                       var elemValue = (VisualElement)Element.GetValue(Accessibility.LabeledByProperty);
+
+                       if (elemValue != null)
+                       {
+                               var id = Control.Id;
+                               if (id == -1)
+                                       id = Control.Id = FormsAppCompatActivity.GetUniqueId();
+
+                               var renderer = elemValue?.GetRenderer();
+                               renderer?.SetLabelFor(id);
+                       }
                }
 
                void UpdateIsEnabled()
index 13f2fff..800a967 100644 (file)
@@ -1,7 +1,19 @@
+using System;
+
 namespace Xamarin.Forms.Platform.Android
 {
        public static class VisualElementExtensions
        {
+               public static IVisualElementRenderer GetRenderer(this VisualElement self)
+               {
+                       if (self == null)
+                               throw new ArgumentNullException("self");
+
+                       IVisualElementRenderer renderer = Platform.GetRenderer(self);
+
+                       return renderer;
+               }
+
                public static bool ShouldBeMadeClickable(this View view)
                {
                        var shouldBeClickable = false;
index c2c96ea..68f5d7d 100644 (file)
@@ -23,6 +23,10 @@ namespace Xamarin.Forms.Platform.Android
 
                VisualElementRendererFlags _flags = VisualElementRendererFlags.AutoPackage | VisualElementRendererFlags.AutoTrack;
 
+               string _defaultContentDescription;
+               bool? _defaultFocusable;
+               string _defaultHint;
+               int? _defaultLabelFor;
                InnerGestureListener _gestureListener;
                VisualElementPackager _packager;
                PropertyChangedEventHandler _propertyChangeHandler;
@@ -209,6 +213,9 @@ namespace Xamarin.Forms.Platform.Android
                        if (element != null && !string.IsNullOrEmpty(element.AutomationId))
                                SetAutomationId(element.AutomationId);
 
+                       SetContentDescription();
+                       SetFocusable();
+
                        Performance.Stop();
                }
 
@@ -300,6 +307,12 @@ namespace Xamarin.Forms.Platform.Android
                                UpdateBackgroundColor();
                        else if (e.PropertyName == VisualElement.InputTransparentProperty.PropertyName)
                                InputTransparent = Element.InputTransparent;
+                       else if (e.PropertyName == Accessibility.HintProperty.PropertyName)
+                               SetContentDescription();
+                       else if (e.PropertyName == Accessibility.NameProperty.PropertyName)
+                               SetContentDescription();
+                       else if (e.PropertyName == Accessibility.IsInAccessibleTreeProperty.PropertyName)
+                               SetFocusable();
                }
 
                protected override void OnLayout(bool changed, int l, int t, int r, int b)
@@ -329,6 +342,62 @@ namespace Xamarin.Forms.Platform.Android
                        ContentDescription = id;
                }
 
+               protected virtual void SetContentDescription()
+               {
+                       if (Element == null)
+                               return;
+
+                       if (SetHint())
+                               return;
+
+                       if (_defaultContentDescription == null)
+                               _defaultContentDescription = ContentDescription;
+
+                       var elemValue = string.Join(" ", (string)Element.GetValue(Accessibility.NameProperty), (string)Element.GetValue(Accessibility.HintProperty));
+
+                       if (!string.IsNullOrWhiteSpace(elemValue))
+                               ContentDescription = elemValue;
+                       else
+                               ContentDescription = _defaultContentDescription;
+               }
+
+               protected virtual void SetFocusable()
+               {
+                       if (Element == null)
+                               return;
+
+                       if (!_defaultFocusable.HasValue)
+                               _defaultFocusable = Focusable;
+
+                       Focusable = (bool)((bool?)Element.GetValue(Accessibility.IsInAccessibleTreeProperty) ?? _defaultFocusable);
+               }
+
+               protected virtual bool SetHint()
+               {
+                       if (Element == null)
+                               return false;
+
+                       var textView = this as global::Android.Widget.TextView;
+                       if (textView == null)
+                               return false;
+
+                       // Let the specified Title/Placeholder take precedence, but don't set the ContentDescription (won't work anyway)
+                       if (((Element as Picker)?.Title ?? (Element as Entry)?.Placeholder ?? (Element as EntryCell)?.Placeholder) != null)
+                               return true;
+
+                       if (_defaultHint == null)
+                               _defaultHint = textView.Hint;
+
+                       var elemValue = string.Join(". ", (string)Element.GetValue(Accessibility.NameProperty), (string)Element.GetValue(Accessibility.HintProperty));
+
+                       if (!string.IsNullOrWhiteSpace(elemValue))
+                               textView.Hint = elemValue;
+                       else
+                               textView.Hint = _defaultHint;
+
+                       return true;
+               }
+
                protected void SetPackager(VisualElementPackager packager)
                {
                        _packager = packager;
@@ -355,6 +424,14 @@ namespace Xamarin.Forms.Platform.Android
                        UpdateGestureRecognizers();
                }
 
+               void IVisualElementRenderer.SetLabelFor(int? id)
+               {
+                       if (_defaultLabelFor == null)
+                               _defaultLabelFor = LabelFor;
+
+                       LabelFor = (int)(id ?? _defaultLabelFor);
+               }
+
                void SubscribeGestureRecognizers(VisualElement element)
                {
                        var view = element as View;
index 0faec61..5844ccf 100644 (file)
@@ -112,6 +112,11 @@ namespace Xamarin.Forms.Platform.UWP
                        return new SizeRequest(new Size(size.Width, size.Height));
                }
 
+               UIElement IVisualElementRenderer.GetNativeElement()
+               {
+                       return Control;
+               }
+
                public void SetElement(VisualElement element)
                {
                        MasterDetailPage old = Element;
index 02b73c9..c278e39 100644 (file)
@@ -122,7 +122,12 @@ namespace Xamarin.Forms.Platform.UWP
             return new SizeRequest(result);
         }
 
-        public void SetElement(VisualElement element)
+               UIElement IVisualElementRenderer.GetNativeElement()
+               {
+                       return Control;
+               }
+
+               public void SetElement(VisualElement element)
         {
             if (element != null && !(element is TabbedPage))
                 throw new ArgumentException("Element must be a TabbedPage", "element");
index 25c4d9e..fe660ff 100644 (file)
@@ -135,6 +135,11 @@ namespace Xamarin.Forms.Platform.WinRT
                        return new SizeRequest(result);
                }
 
+               UIElement IVisualElementRenderer.GetNativeElement()
+               {
+                       return null;
+               }
+
                public void Dispose()
                {
                        Dispose(true);
index 2cfc241..2ac48dd 100644 (file)
@@ -144,6 +144,11 @@ namespace Xamarin.Forms.Platform.WinRT
                        return new SizeRequest(result);
                }
 
+               UIElement IVisualElementRenderer.GetNativeElement()
+               {
+                       return null;
+               }
+
                public void Dispose()
                {
                        Dispose(true);
index 11f4e09..33e0939 100644 (file)
@@ -70,6 +70,11 @@ namespace Xamarin.Forms.Platform.WinRT
                        return new SizeRequest(result);
                }
 
+               UIElement IVisualElementRenderer.GetNativeElement()
+               {
+                       return null;
+               }
+
                public void SetElement(VisualElement element)
                {
                        var newPage = element as CarouselPage;
index 4db9c1a..abae812 100644 (file)
@@ -18,6 +18,9 @@ namespace Xamarin.Forms.Platform.WinRT
                event EventHandler<VisualElementChangedEventArgs> ElementChanged;
 
                SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint);
+
                void SetElement(VisualElement element);
+
+               UIElement GetNativeElement();
        }
 }
\ No newline at end of file
index db581d5..031e2cf 100644 (file)
@@ -77,9 +77,6 @@ namespace Xamarin.Forms.Platform.WinRT
                                        // and prevented from bubbling up) rather than ListView.ItemClick
                                        List.Tapped += ListOnTapped;
 
-                                       // We also want to watch for the Enter key being pressed for selection
-                                       List.KeyUp += OnKeyPressed;
-                                       
                                        List.SelectionChanged += OnControlSelectionChanged;
 
                                        List.SetBinding(ItemsControl.ItemsSourceProperty, "");
@@ -141,7 +138,6 @@ namespace Xamarin.Forms.Platform.WinRT
                        if (List != null)
                        {
                                List.Tapped -= ListOnTapped;
-                               List.KeyUp -= OnKeyPressed;
 
                                List.SelectionChanged -= OnControlSelectionChanged;
 
@@ -508,17 +504,6 @@ namespace Xamarin.Forms.Platform.WinRT
 #endif
                }
 
-               void OnKeyPressed(object sender, KeyRoutedEventArgs e)
-               {
-                       if (e.Key == VirtualKey.Enter)
-                       {
-                               if (Element.SelectedItem != null && Element.SelectedItem != List.SelectedItem)
-                               {
-                                       ((IElementController)Element).SetValueFromRenderer(ListView.SelectedItemProperty, List.SelectedItem);
-                               }
-                       }
-               }
-
                void OnControlSelectionChanged(object sender, SelectionChangedEventArgs e)
                {
                        RestorePreviousSelectedVisual();
@@ -540,6 +525,10 @@ namespace Xamarin.Forms.Platform.WinRT
                                }
                        }
 #endif
+
+                       // A11y: Tapped event will not be routed when Narrator is active
+                       // Also handles keyboard selection
+                       SelectElementItem();
                }
 
                FrameworkElement FindElement(object cell)
@@ -553,6 +542,15 @@ namespace Xamarin.Forms.Platform.WinRT
                        return null;
                }
 
+               void SelectElementItem()
+               {
+                       if (List.SelectedItem != null && Element.SelectedItem != List.SelectedItem)
+                       {
+                               ((IElementController)Element).SetValueFromRenderer(ListView.SelectedItemProperty, List?.SelectedItem);
+                               OnElementItemSelected(null, new SelectedItemChangedEventArgs(Element?.SelectedItem));
+                       }
+               }
+
 #if WINDOWS_UWP
                void RestorePreviousSelectedVisual()
                {
index 414870c..dcef680 100644 (file)
@@ -94,6 +94,11 @@ namespace Xamarin.Forms.Platform.WinRT
 
                public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
 
+               UIElement IVisualElementRenderer.GetNativeElement()
+               {
+                       return null;
+               }
+
                public SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
                {
                        return new SizeRequest(new Size(Device.Info.ScaledScreenSize.Width, Device.Info.ScaledScreenSize.Height));
index e7e0184..5229fdc 100644 (file)
@@ -137,6 +137,11 @@ namespace Xamarin.Forms.Platform.WinRT
                        return new SizeRequest(result);
                }
 
+               UIElement IVisualElementRenderer.GetNativeElement()
+               {
+                       return null;
+               }
+
                public void SetElement(VisualElement element)
                {
                        if (element != null && !(element is NavigationPage))
index 148da1b..0017531 100644 (file)
@@ -1,5 +1,6 @@
 using Windows.UI.Xaml;
 using Windows.UI.Xaml.Automation;
+using Windows.UI.Xaml.Automation.Peers;
 
 #if WINDOWS_UWP
 
@@ -11,6 +12,11 @@ namespace Xamarin.Forms.Platform.WinRT
 {
        public class ViewRenderer<TElement, TNativeElement> : VisualElementRenderer<TElement, TNativeElement> where TElement : View where TNativeElement : FrameworkElement
        {
+               string _defaultAutomationPropertiesName;
+               AccessibilityView? _defaultAutomationPropertiesAccessibilityView;
+               string _defaultAutomationPropertiesHelpText;
+               UIElement _defaultAutomationPropertiesLabeledBy;
+
                protected override void OnElementChanged(ElementChangedEventArgs<TElement> e)
                {
                        base.OnElementChanged(e);
@@ -33,5 +39,97 @@ namespace Xamarin.Forms.Platform.WinRT
                                Control.SetValue(AutomationProperties.AutomationIdProperty, id);
                        }
                }
+               protected override void SetAutomationPropertiesName()
+               {
+                       if (Control == null)
+                       {
+                               base.SetAutomationPropertiesName();
+                               return;
+                       }
+
+                       if (Element == null)
+                               return;
+
+                       if (_defaultAutomationPropertiesName == null)
+                               _defaultAutomationPropertiesName = (string)Control.GetValue(AutomationProperties.NameProperty);
+
+                       var elemValue = (string)Element.GetValue(Accessibility.NameProperty);
+
+                       if (!string.IsNullOrWhiteSpace(elemValue))
+                               Control.SetValue(AutomationProperties.NameProperty, elemValue);
+                       else
+                               Control.SetValue(AutomationProperties.NameProperty, _defaultAutomationPropertiesName);
+               }
+
+               protected override void SetAutomationPropertiesAccessibilityView()
+               {
+                       if (Control == null)
+                       {
+                               base.SetAutomationPropertiesAccessibilityView();
+                               return;
+                       }
+
+                       if (Element == null)
+                               return;
+
+                       if (!_defaultAutomationPropertiesAccessibilityView.HasValue)
+                               _defaultAutomationPropertiesAccessibilityView = (AccessibilityView)Control.GetValue(AutomationProperties.AccessibilityViewProperty);
+
+                       var newValue = _defaultAutomationPropertiesAccessibilityView;
+                       var elemValue = (bool?)Element.GetValue(Accessibility.IsInAccessibleTreeProperty);
+
+                       if (elemValue == true)
+                               newValue = AccessibilityView.Content;
+                       else if (elemValue == false)
+                               newValue = AccessibilityView.Raw;
+
+                       Control.SetValue(AutomationProperties.AccessibilityViewProperty, newValue);
+               }
+
+               protected override void SetAutomationPropertiesHelpText()
+               {
+                       if (Control == null)
+                       {
+                               base.SetAutomationPropertiesHelpText();
+                               return;
+                       }
+
+                       if (Element == null)
+                               return;
+
+                       if (_defaultAutomationPropertiesHelpText == null)
+                               _defaultAutomationPropertiesHelpText = (string)Control.GetValue(AutomationProperties.HelpTextProperty);
+
+                       var elemValue = (string)Element.GetValue(Accessibility.HintProperty);
+
+                       if (!string.IsNullOrWhiteSpace(elemValue))
+                               Control.SetValue(AutomationProperties.HelpTextProperty, elemValue);
+                       else
+                               Control.SetValue(AutomationProperties.HelpTextProperty, _defaultAutomationPropertiesHelpText);
+               }
+
+               protected override void SetAutomationPropertiesLabeledBy()
+               {
+                       if (Control == null)
+                       {
+                               base.SetAutomationPropertiesLabeledBy(); 
+                               return;
+                       }
+
+                       if (Element == null)
+                               return;
+
+                       if (_defaultAutomationPropertiesLabeledBy == null)
+                               _defaultAutomationPropertiesLabeledBy = (UIElement)Control.GetValue(AutomationProperties.LabeledByProperty);
+
+                       var elemValue = (VisualElement)Element.GetValue(Accessibility.LabeledByProperty);
+                       var renderer = elemValue?.GetOrCreateRenderer();
+                       var nativeElement = renderer?.GetNativeElement();
+
+                       if (nativeElement != null)
+                               Control.SetValue(AutomationProperties.LabeledByProperty, nativeElement);
+                       else
+                               Control.SetValue(AutomationProperties.LabeledByProperty, _defaultAutomationPropertiesLabeledBy);
+               }
        }
 }
\ No newline at end of file
index b81f73e..402d1da 100644 (file)
@@ -4,6 +4,7 @@ using System.ComponentModel;
 using Windows.Foundation;
 using Windows.UI.Xaml;
 using Windows.UI.Xaml.Automation;
+using Windows.UI.Xaml.Automation.Peers;
 using Windows.UI.Xaml.Controls;
 
 #if WINDOWS_UWP
@@ -17,6 +18,10 @@ namespace Xamarin.Forms.Platform.WinRT
        public class VisualElementRenderer<TElement, TNativeElement> : Panel, IVisualElementRenderer, IDisposable, IEffectControlProvider where TElement : VisualElement
                                                                                                                                                                                                                                                                          where TNativeElement : FrameworkElement
        {
+               string _defaultAutomationPropertiesName;
+               AccessibilityView? _defaultAutomationPropertiesAccessibilityView;
+               string _defaultAutomationPropertiesHelpText;
+               UIElement _defaultAutomationPropertiesLabeledBy;
                bool _disposed;
                EventHandler<VisualElementChangedEventArgs> _elementChangedHandlers;
                VisualElementTracker<TElement, TNativeElement> _tracker;
@@ -108,6 +113,11 @@ namespace Xamarin.Forms.Platform.WinRT
                        return new SizeRequest(result);
                }
 
+               public UIElement GetNativeElement()
+               {
+                       return Control;
+               }
+
                public void SetElement(VisualElement element)
                {
                        TElement oldElement = Element;
@@ -287,6 +297,14 @@ namespace Xamarin.Forms.Platform.WinRT
                                UpdateEnabled();
                        else if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
                                UpdateBackgroundColor();
+                       else if (e.PropertyName == Accessibility.HintProperty.PropertyName)
+                               SetAutomationPropertiesHelpText();
+                       else if (e.PropertyName == Accessibility.NameProperty.PropertyName)
+                               SetAutomationPropertiesName();
+                       else if (e.PropertyName == Accessibility.IsInAccessibleTreeProperty.PropertyName)
+                               SetAutomationPropertiesAccessibilityView();
+                       else if (e.PropertyName == Accessibility.LabeledByProperty.PropertyName)
+                               SetAutomationPropertiesLabeledBy();
                }
 
                protected virtual void OnRegisterEffect(PlatformEffect effect)
@@ -300,6 +318,75 @@ namespace Xamarin.Forms.Platform.WinRT
                        SetValue(AutomationProperties.AutomationIdProperty, id);
                }
 
+               protected virtual void SetAutomationPropertiesName()
+               {
+                       if (Element == null || Control == null)
+                               return;
+
+                       if (_defaultAutomationPropertiesName == null)
+                               _defaultAutomationPropertiesName = (string)Control.GetValue(AutomationProperties.NameProperty);
+
+                       var elemValue = (string)Element.GetValue(Accessibility.NameProperty);
+
+                       if (!string.IsNullOrWhiteSpace(elemValue))
+                               Control.SetValue(AutomationProperties.NameProperty, elemValue);
+                       else
+                               Control.SetValue(AutomationProperties.NameProperty, _defaultAutomationPropertiesName);
+               }
+
+               protected virtual void SetAutomationPropertiesAccessibilityView()
+               {
+                       if (Element == null || Control == null)
+                               return;
+
+                       if (!_defaultAutomationPropertiesAccessibilityView.HasValue)
+                               _defaultAutomationPropertiesAccessibilityView = (AccessibilityView)Control.GetValue(AutomationProperties.AccessibilityViewProperty);
+
+                       var newValue = _defaultAutomationPropertiesAccessibilityView;
+                       var elemValue = (bool?)Element.GetValue(Accessibility.IsInAccessibleTreeProperty);
+
+                       if (elemValue == true)
+                               newValue = AccessibilityView.Content;
+                       else if (elemValue == false)
+                               newValue = AccessibilityView.Raw;
+
+                       Control.SetValue(AutomationProperties.AccessibilityViewProperty, newValue);
+               }
+
+               protected virtual void SetAutomationPropertiesHelpText()
+               {
+                       if (Element == null || Control == null)
+                               return;
+
+                       if (_defaultAutomationPropertiesHelpText == null)
+                               _defaultAutomationPropertiesHelpText = (string)Control.GetValue(AutomationProperties.HelpTextProperty);
+
+                       var elemValue = (string)Element.GetValue(Accessibility.HintProperty);
+
+                       if (!string.IsNullOrWhiteSpace(elemValue))
+                               Control.SetValue(AutomationProperties.HelpTextProperty, elemValue);
+                       else
+                               Control.SetValue(AutomationProperties.HelpTextProperty, _defaultAutomationPropertiesHelpText);
+               }
+
+               protected virtual void SetAutomationPropertiesLabeledBy()
+               {
+                       if (Element == null || Control == null)
+                               return;
+
+                       if (_defaultAutomationPropertiesLabeledBy == null)
+                               _defaultAutomationPropertiesLabeledBy = (UIElement)Control.GetValue(AutomationProperties.LabeledByProperty);
+
+                       var elemValue = (VisualElement)Element.GetValue(Accessibility.LabeledByProperty);
+                       var renderer = elemValue?.GetOrCreateRenderer();
+                       var nativeElement = renderer?.GetNativeElement();
+
+                       if (nativeElement != null)
+                               Control.SetValue(AutomationProperties.LabeledByProperty, nativeElement);
+                       else
+                               Control.SetValue(AutomationProperties.LabeledByProperty, _defaultAutomationPropertiesLabeledBy);
+               }
+
                protected void SetNativeControl(TNativeElement control)
                {
                        TNativeElement oldControl = Control;
@@ -367,6 +454,10 @@ namespace Xamarin.Forms.Platform.WinRT
                protected virtual void UpdateNativeControl()
                {
                        UpdateEnabled();
+                       SetAutomationPropertiesHelpText();
+                       SetAutomationPropertiesName();
+                       SetAutomationPropertiesAccessibilityView();
+                       SetAutomationPropertiesLabeledBy();
                }
 
                internal virtual void OnElementFocusChangeRequested(object sender, VisualElement.FocusRequestArgs args)
index 68d4702..3e99cd5 100644 (file)
@@ -86,6 +86,21 @@ namespace Xamarin.Forms.Platform.iOS
                                UpdateImage();
                }
 
+               protected override void SetAccessibilityLabel()
+               {
+                       // If we have not specified an AccessibilityLabel and the AccessibiltyLabel is current bound to the Title,
+                       // exit this method so we don't set the AccessibilityLabel value and break the binding.
+                       // This may pose a problem for users who want to explicitly set the AccessibilityLabel to null, but this
+                       // will prevent us from inadvertently breaking UI Tests that are using Query.Marked to get the dynamic Title 
+                       // of the Button.
+
+                       var elemValue = (string)Element?.GetValue(Accessibility.NameProperty);
+                       if (string.IsNullOrWhiteSpace(elemValue) && Control?.AccessibilityLabel == Control?.Title(UIControlState.Normal))
+                               return;
+
+                       base.SetAccessibilityLabel();
+               }
+
                void OnButtonTouchUpInside(object sender, EventArgs eventArgs)
                {
                        ((IButtonController)Element)?.SendClicked();
index 445abf3..82ceda8 100644 (file)
@@ -137,6 +137,23 @@ namespace Xamarin.Forms.Platform.MacOS
                                UpdateLineBreakMode();
                }
 
+#if __MOBILE__
+               protected override void SetAccessibilityLabel()
+               {
+                       // If we have not specified an AccessibilityLabel and the AccessibiltyLabel is current bound to the Text,
+                       // exit this method so we don't set the AccessibilityLabel value and break the binding.
+                       // This may pose a problem for users who want to explicitly set the AccessibilityLabel to null, but this
+                       // will prevent us from inadvertently breaking UI Tests that are using Query.Marked to get the dynamic Text 
+                       // of the Label.
+
+                       var elemValue = (string)Element?.GetValue(Accessibility.NameProperty);
+                       if (string.IsNullOrWhiteSpace(elemValue) && Control?.AccessibilityLabel == Control?.Text)
+                               return;
+
+                       base.SetAccessibilityLabel();
+               }
+#endif
+
                protected override void SetBackgroundColor(Color color)
                {
 #if __MOBILE__
index 01f8e06..2cf9f75 100644 (file)
@@ -25,6 +25,11 @@ namespace Xamarin.Forms.Platform.MacOS
 
        public abstract class ViewRenderer<TView, TNativeView> : VisualElementRenderer<TView> where TView : View where TNativeView : NativeView
        {
+#if __MOBILE__
+               string _defaultAccessibilityLabel;
+               string _defaultAccessibilityHint;
+               bool? _defaultIsAccessibilityElement;
+#endif
                NativeColor _defaultColor;
 
                public TNativeView Control { get; private set; }
@@ -110,7 +115,59 @@ namespace Xamarin.Forms.Platform.MacOS
                        base.OnRegisterEffect(effect);
                        effect.Control = Control;
                }
+#if __MOBILE__
+               protected override void SetAccessibilityHint()
+               {
+                       if (Control == null)
+                       {
+                               base.SetAccessibilityHint();
+                               return;
+                       }
+
+                       if (Element == null)
+                               return;
+
+                       if (_defaultAccessibilityHint == null)
+                               _defaultAccessibilityHint = Control.AccessibilityHint;
+
+                       Control.AccessibilityHint = (string)Element.GetValue(Accessibility.HintProperty) ?? _defaultAccessibilityHint;
+
+               }
+
+               protected override void SetAccessibilityLabel()
+               {
+                       if (Control == null)
+                       {
+                               base.SetAccessibilityLabel();
+                               return;
+                       }
+
+                       if (Element == null)
+                               return;
+
+                       if (_defaultAccessibilityLabel == null)
+                               _defaultAccessibilityLabel = Control.AccessibilityLabel;
+
+                       Control.AccessibilityLabel = (string)Element.GetValue(Accessibility.NameProperty) ?? _defaultAccessibilityLabel;
+               }
+
+               protected override void SetIsAccessibilityElement()
+               {
+                       if (Control == null)
+                       {
+                               base.SetIsAccessibilityElement();
+                               return;
+                       }
 
+                       if (Element == null)
+                               return;
+
+                       if (!_defaultIsAccessibilityElement.HasValue)
+                               _defaultIsAccessibilityElement = Control.IsAccessibilityElement;
+
+                       Control.IsAccessibilityElement = (bool)((bool?)Element.GetValue(Accessibility.IsInAccessibleTreeProperty) ?? _defaultIsAccessibilityElement);
+               }
+#endif
                protected override void SetAutomationId(string id)
                {
                        if (Control == null)
index 0e7af2a..57c9ab1 100644 (file)
@@ -36,6 +36,11 @@ namespace Xamarin.Forms.Platform.MacOS
                readonly List<EventHandler<VisualElementChangedEventArgs>> _elementChangedHandlers = new List<EventHandler<VisualElementChangedEventArgs>>();
 
                readonly PropertyChangedEventHandler _propertyChangedHandler;
+#if __MOBILE__
+               string _defaultAccessibilityLabel;
+               string _defaultAccessibilityHint;
+               bool? _defaultIsAccessibilityElement;
+#endif
                EventTracker _events;
 
                VisualElementRendererFlags _flags = VisualElementRendererFlags.AutoPackage | VisualElementRendererFlags.AutoTrack;
@@ -177,6 +182,7 @@ namespace Xamarin.Forms.Platform.MacOS
                                }
 
                                element.PropertyChanged += _propertyChangedHandler;
+
                        }
 
                        OnElementChanged(new ElementChangedEventArgs<TElement>(oldElement, element));
@@ -188,6 +194,11 @@ namespace Xamarin.Forms.Platform.MacOS
 
                        if (Element != null && !string.IsNullOrEmpty(Element.AutomationId))
                                SetAutomationId(Element.AutomationId);
+#if __MOBILE__
+                       SetAccessibilityLabel();
+                       SetAccessibilityHint();
+                       SetIsAccessibilityElement();
+#endif
                }
 
 #if __MOBILE__
@@ -269,6 +280,12 @@ namespace Xamarin.Forms.Platform.MacOS
 #if __MOBILE__
                        else if (e.PropertyName == PlatformConfiguration.iOSSpecific.VisualElement.BlurEffectProperty.PropertyName)
                                SetBlur((BlurEffectStyle)Element.GetValue(PlatformConfiguration.iOSSpecific.VisualElement.BlurEffectProperty));
+                       else if (e.PropertyName == Accessibility.HintProperty.PropertyName)
+                               SetAccessibilityHint();
+                       else if (e.PropertyName == Accessibility.NameProperty.PropertyName)
+                               SetAccessibilityLabel();
+                       else if (e.PropertyName == Accessibility.IsInAccessibleTreeProperty.PropertyName)
+                               SetIsAccessibilityElement();
 #endif
                }
 
@@ -277,6 +294,40 @@ namespace Xamarin.Forms.Platform.MacOS
                        effect.Container = this;
                }
 
+#if __MOBILE__
+               protected virtual void SetAccessibilityHint()
+               {
+                       if (Element == null)
+                               return;
+
+                       if (_defaultAccessibilityHint == null)
+                               _defaultAccessibilityHint = AccessibilityHint;
+
+                       AccessibilityHint = (string)Element.GetValue(Accessibility.HintProperty) ?? _defaultAccessibilityHint;
+               }
+
+               protected virtual void SetAccessibilityLabel()
+               {
+                       if (Element == null)
+                               return;
+
+                       if (_defaultAccessibilityLabel == null)
+                               _defaultAccessibilityLabel = AccessibilityLabel;
+
+                       AccessibilityLabel = (string)Element.GetValue(Accessibility.NameProperty) ?? _defaultAccessibilityLabel;
+               }
+
+               protected virtual void SetIsAccessibilityElement()
+               {
+                       if (Element == null)
+                               return;
+
+                       if (!_defaultIsAccessibilityElement.HasValue)
+                               _defaultIsAccessibilityElement = IsAccessibilityElement;
+
+                       IsAccessibilityElement = (bool)((bool?)Element.GetValue(Accessibility.IsInAccessibleTreeProperty) ?? _defaultIsAccessibilityElement);
+               }
+#endif
                protected virtual void SetAutomationId(string id)
                {
                        AccessibilityIdentifier = id;
@@ -286,11 +337,11 @@ namespace Xamarin.Forms.Platform.MacOS
                {
                        if (color == Color.Default)
 #if __MOBILE__
-                       
+
                                BackgroundColor = _defaultColor;
                        else
                                BackgroundColor = color.ToUIColor();
-                               
+
 #else
                                Layer.BackgroundColor = _defaultColor.CGColor;
                        else
diff --git a/docs/Xamarin.Forms.Core/Xamarin.Forms/Accessibility.xml b/docs/Xamarin.Forms.Core/Xamarin.Forms/Accessibility.xml
new file mode 100644 (file)
index 0000000..c18c73e
--- /dev/null
@@ -0,0 +1,91 @@
+<Type Name="Accessibility" FullName="Xamarin.Forms.Accessibility">
+  <TypeSignature Language="C#" Value="public class Accessibility" />
+  <TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit Accessibility 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>To be added.</summary>
+    <remarks>To be added.</remarks>
+  </Docs>
+  <Members>
+    <Member MemberName=".ctor">
+      <MemberSignature Language="C#" Value="public Accessibility ();" />
+      <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="HintProperty">
+      <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty HintProperty;" />
+      <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty HintProperty" />
+      <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="IsInAccessibleTreeProperty">
+      <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty IsInAccessibleTreeProperty;" />
+      <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty IsInAccessibleTreeProperty" />
+      <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="LabeledByProperty">
+      <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty LabeledByProperty;" />
+      <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty LabeledByProperty" />
+      <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="NameProperty">
+      <MemberSignature Language="C#" Value="public static readonly Xamarin.Forms.BindableProperty NameProperty;" />
+      <MemberSignature Language="ILAsm" Value=".field public static initonly class Xamarin.Forms.BindableProperty NameProperty" />
+      <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>
+  </Members>
+</Type>