diff --git a/Sample Applications/WPFGallery/Controls/IconDataField.xaml b/Sample Applications/WPFGallery/Controls/IconDataField.xaml new file mode 100644 index 000000000..32846c0a8 --- /dev/null +++ b/Sample Applications/WPFGallery/Controls/IconDataField.xaml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + diff --git a/Sample Applications/WPFGallery/Controls/IconDataField.xaml.cs b/Sample Applications/WPFGallery/Controls/IconDataField.xaml.cs new file mode 100644 index 000000000..2beb4b690 --- /dev/null +++ b/Sample Applications/WPFGallery/Controls/IconDataField.xaml.cs @@ -0,0 +1,63 @@ +using System.Windows.Automation; +using System.Windows.Automation.Peers; + +namespace WPFGallery.Controls +{ + /// + /// Interaction logic for IconDataField.xaml. + /// Displays a single read-only icon metadata value (e.g. icon name, Unicode + /// code point or glyph) together with a button that copies the value to the + /// clipboard. The value is rendered by a TextBlock that lives in the + /// control's content tree, so it is exposed to UI Automation as content and + /// is reachable by Narrator scan mode. + /// + public partial class IconDataField : UserControl + { + public IconDataField() + { + InitializeComponent(); + } + + public string Value + { + get { return (string)GetValue(ValueProperty); } + set { SetValue(ValueProperty, value); } + } + + public static readonly DependencyProperty ValueProperty = + DependencyProperty.Register(nameof(Value), typeof(string), typeof(IconDataField), new PropertyMetadata(string.Empty)); + + public string Label + { + get { return (string)GetValue(LabelProperty); } + set { SetValue(LabelProperty, value); } + } + + public static readonly DependencyProperty LabelProperty = + DependencyProperty.Register(nameof(Label), typeof(string), typeof(IconDataField), new PropertyMetadata(string.Empty)); + + private void CopyButton_Click(object sender, RoutedEventArgs e) + { + if (string.IsNullOrEmpty(Value)) + { + return; + } + + try + { + Clipboard.SetText(Value); + AutomationPeer peer = UIElementAutomationPeer.CreatePeerForElement(this); + peer?.RaiseNotificationEvent( + AutomationNotificationKind.Other, + AutomationNotificationProcessing.ImportantMostRecent, + $"{Label} Copied", + "ButtonClickedActivity" + ); + } + catch (Exception ex) + { + MessageBox.Show("Error copying to clipboard: " + ex.Message); + } + } + } +} diff --git a/Sample Applications/WPFGallery/Views/DesignGuidance/ColorsPage.xaml b/Sample Applications/WPFGallery/Views/DesignGuidance/ColorsPage.xaml index 7cc6e390e..8b8be85b7 100644 --- a/Sample Applications/WPFGallery/Views/DesignGuidance/ColorsPage.xaml +++ b/Sample Applications/WPFGallery/Views/DesignGuidance/ColorsPage.xaml @@ -5,7 +5,6 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:WPFGallery.Views" xmlns:controls="clr-namespace:WPFGallery.Controls" - xmlns:sys="clr-namespace:System;assembly=mscorlib" mc:Ignorable="d" Foreground="{DynamicResource TextFillColorPrimaryBrush}" d:DesignHeight="450" d:DesignWidth="800" @@ -36,12 +35,12 @@ - Text - Fill - Stroke - Background - Signal - HighContrast + + + + + + diff --git a/Sample Applications/WPFGallery/Views/DesignGuidance/ColorsPage.xaml.cs b/Sample Applications/WPFGallery/Views/DesignGuidance/ColorsPage.xaml.cs index eaa2cff32..67924a89b 100644 --- a/Sample Applications/WPFGallery/Views/DesignGuidance/ColorsPage.xaml.cs +++ b/Sample Applications/WPFGallery/Views/DesignGuidance/ColorsPage.xaml.cs @@ -1,4 +1,4 @@ -using System.Windows.Documents; +using System.Windows.Documents; using System.Windows.Navigation; using System.Windows.Shapes; using WPFGallery.ViewModels; @@ -46,6 +46,16 @@ private void OnSelectionChanged(object sender, SelectionChangedEventArgs e) private void OnLoaded(object sender, RoutedEventArgs e) { PageSelector.SelectedItem = PageSelector.Items[0]; + + // A ComboBox builds its item containers lazily, only when its drop-down + // is first opened. Until then there are no container automation peers, so + // WPF raises no UI Automation selection event when the selection changes + // via the arrow keys on the collapsed control and Narrator stays silent. + // Open and immediately close the drop-down once to realize the containers + // up front (PopupAnimation is None, so this is not visible). The containers + // persist after closing, so the native selection event then fires correctly. + PageSelector.IsDropDownOpen = true; + PageSelector.IsDropDownOpen = false; } } } diff --git a/Sample Applications/WPFGallery/Views/DesignGuidance/IconsPage.xaml b/Sample Applications/WPFGallery/Views/DesignGuidance/IconsPage.xaml index 7f5e0952c..def005a54 100644 --- a/Sample Applications/WPFGallery/Views/DesignGuidance/IconsPage.xaml +++ b/Sample Applications/WPFGallery/Views/DesignGuidance/IconsPage.xaml @@ -18,61 +18,6 @@ - - - -