Let’s say I’ve got to the effort of creating a modal dialog or it’s equivalent in a Silverlight application. What I would like to complete the picture is a “default” button, so that if I hit the Enter key while in a text box, the dialog will be “submitted”. There are probably several ways of achieving this end, but I wanted something that was simple, and encapsulated in an attached property so the consumer wouldn’t have to deal with much code. I wrote the attached property so that I could use it on text boxes like this
<TextBox x:Name="theText" VerticalAlignment="Center" Margin="10,0,10,0" Grid.Row="0" my:DefaultButtonService.DefaultButton="theButton"/>
where “theButton” here is the default button I want to be pressed when the Enter key happens inside my text box. The downside is that I have to apply this property to every text box on the page, but so be it, that seems like a relatively small price to pay. So I got as far as finding the named button in the visual tree, but the the question was, how to “press” the button. The Button class in Silverlight has a protected OnClick that would do the trick, if it wasn’t protected. I could derive my own control from Button and expose the OnClick method, but ewww. If I did that then every dialog that wanted this behavior would have to remember to use the derived Button class. I tried reflecting over the Button and Invoking OnClick anyway, but turns out you get a security exception. OK. Then, thanks to a presentation Stuart gave us yesterday on Accessibility, I remembered the Automation framework in Silverlight. That turned out to be super easy, just create an instance of ButtonAutmationPeer from the Button, then Invoke it. Cool.
public static class DefaultButtonService { public static readonly DependencyProperty DefaultButtonProperty = DependencyProperty.RegisterAttached("DefaultButton", typeof(string), typeof(DefaultButtonService), new PropertyMetadata(OnDefaultButtonChanged)); public static string GetDefaultButton(DependencyObject d) { return (string)d.GetValue(DefaultButtonProperty); } /// <summary> /// Sets the CommandParameter property. /// </summary> public static void SetDefaultButton(DependencyObject d, string value) { d.SetValue(DefaultButtonProperty, value); } private static void OnDefaultButtonChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TextBox tb = d as TextBox; if (tb != null) { tb.KeyUp += new KeyEventHandler(tb_KeyUp); } } static void tb_KeyUp(object sender, KeyEventArgs e) { switch (e.Key) { case Key.Enter: string name = (string)((DependencyObject)sender).GetValue(DefaultButtonProperty); object root = App.Current.RootVisual; object button = ((FrameworkElement)root).FindName(name); if (button is Button) { ButtonAutomationPeer peer = new ButtonAutomationPeer((Button)button); IInvokeProvider ip = (IInvokeProvider)peer; ip.Invoke(); } break; } } }
Powered by: newtelligence dasBlog 1.9.6264.0
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.
© Copyright 2010, Patrick Cauldwell
E-mail