Служба кнопок Silverlight 4 по умолчанию - PullRequest
5 голосов
/ 21 апреля 2010

В течение нескольких месяцев я успешно использовал Пример кнопки Дэвида Джастиса по умолчанию в моем приложении SL 3. Этот подход основан на прикрепленном свойстве.

После обновления до SL4 подход больше не работает, и я получаю исключение XAML:

Неизвестная ошибка анализатора: Сканер 2148474880

Кто-нибудь успешно использовал это (или любое другое) поведение по умолчанию, прикрепленное к кнопке в SL4?

Есть ли другой способ добиться поведения кнопки по умолчанию в SL4 с помощью новых доступных классов?

Спасибо, Mark

Ответы [ 5 ]

8 голосов
/ 09 июля 2010

Окончательное решение для нас также должно было обойти проблему, когда свойство поддержки не обновлялось до нажатия кнопки (как во всех шаблонах MVVM) .... Примечание: peer.SetFocus();

Edit: Добавлен пример XAML.

public static class DefaultButtonService
{
    public static DependencyProperty DefaultButtonProperty =
          DependencyProperty.RegisterAttached("DefaultButton",
                                              typeof(Button),
                                              typeof(DefaultButtonService),
                                              new PropertyMetadata(null, DefaultButtonChanged));

    private static void DefaultButtonChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
        var uiElement = d as UIElement;
        var button = e.NewValue as Button;
        if (uiElement != null && button != null) {
            uiElement.KeyUp += (sender, arg) => {
                var peer = new ButtonAutomationPeer(button);

                if (arg.Key == Key.Enter) {
                    peer.SetFocus();
                    uiElement.Dispatcher.BeginInvoke((Action)delegate {

                        var invokeProv =
                            peer.GetPattern(PatternInterface.Invoke) as IInvokeProvider;
                        if (invokeProv != null)
                            invokeProv.Invoke();
                    });
                }
            };
        }

    }

    public static Button GetDefaultButton(UIElement obj) {
        return (Button)obj.GetValue(DefaultButtonProperty);
    }

    public static void SetDefaultButton(DependencyObject obj, Button button) {
        obj.SetValue(DefaultButtonProperty, button);
    }       
}

Как подать заявку в XAML:

<StackPanel>
    <TextBox DinnerConfig:DefaultButtonService.DefaultButton="{Binding ElementName=MyButton}"
                Text="Press Enter" />
    <Button x:Name="MyButton"
            Content="Click me" />
</StackPanel>
3 голосов
/ 29 апреля 2010

Я действительно надеялся, что в Silverlight 4 найдется готовое решение для такого распространенного варианта использования, но, к сожалению, я не думаю, что оно есть.

Есть еще одна реализация кнопки по умолчанию от Патрика Колдуэлла. Он также использует Attached Properties.

Я протестировал это в приложении SL 4, и, похоже, он справился с работой.

Вы можете найти код здесь: http://www.cauldwell.net/patrick/blog/DefaultButtonSemanticsInSilverlightRevisited.aspx

Edit: Я настроил код Дэвида Джастиса, чтобы он работал для Silverlight 4. Я только что изменил GetDefaultButton и SetDefaultButton, чтобы принимать и возвращать DefaultButtonService. Использование такое же, как отмечено на его сайте. Это должно работать для вас:

Edit2: Добавлен пример XAML для наглядности.

public class DefaultButtonService
    {
        public static DependencyProperty DefaultButtonProperty =
            DependencyProperty.RegisterAttached("DefaultButton",
                                                typeof(Button),
                                                typeof(DefaultButtonService),
                                                new PropertyMetadata(null, DefaultButtonChanged));

        private static void DefaultButtonChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var uiElement = d as UIElement;
            var button = e.NewValue as Button;
            if (uiElement != null && button != null)
            {
                uiElement.KeyUp += (sender, arg) =>
                {
                    if (arg.Key == Key.Enter)
                    {
                        var peer = new ButtonAutomationPeer(button);
                        var invokeProv =
                            peer.GetPattern(PatternInterface.Invoke) as IInvokeProvider;
                        if (invokeProv != null)
                            invokeProv.Invoke();
                    }
                };
            }
        }

        public static DefaultButtonService GetDefaultButton(UIElement obj)
        {
            return (DefaultButtonService)obj.GetValue(DefaultButtonProperty);
        }

        public static void SetDefaultButton(DependencyObject obj, DefaultButtonService button)
        {
            obj.SetValue(DefaultButtonProperty, button);
        }        
    }

Как подать заявку в XAML:

<StackPanel>
    <TextBox DinnerConfig:DefaultButtonService.DefaultButton="{Binding ElementName=MyButton}"
                Text="Press Enter" />
    <Button x:Name="MyButton"
            Content="Click me" />
</StackPanel>
2 голосов
/ 26 мая 2010

Я расширил подход Дэвида, позволив установить дополнительный ключ (по умолчанию Enter) в дополнительном свойстве:

    public static DependencyProperty ButtonKeyProperty = DependencyProperty.RegisterAttached(
         "ButtonKey",
         typeof(Key),
         typeof(Defaults),
         new PropertyMetadata(Key.Enter, ButtonChanged));

    public static void SetButtonKey(DependencyObject dependencyObj, Key key)
    {
        dependencyObj.SetValue(ButtonKeyProperty, key);
    }

    public static Key GetButtonKey(DependencyObject dependencyObj)
    {
        return (Key)dependencyObj.GetValue(ButtonKeyProperty);
    }

Я изменил исходное свойство, чтобы затем использовать это свойство:

    Key key = GetButtonKey(dependencyObj);
    if (button.IsEnabled && keyEvent.Key == key)
        ...

Так что теперь, например, я могу использовать Escape в качестве ключа, если я хочу (заметьте, я изменил имена классов и свойств):

    ... UI:Defaults.Button="{Binding ElementName=myButton}" UI:Defaults.ButtonKey="Escape" ...
0 голосов
/ 20 декабря 2012

Вот простой способ подключить кнопку по умолчанию при нажатии Enter:

По соображениям безопасности Silverlight не позволит вам вызывать обработчик кнопок непосредственно в коде, поэтому мы должны создать новую подпрограмму, которая может быть вызвана, а затем обработчик кнопок и обработчик клавиш формы вызвать эту подпрограмму. *

Шаг 1: создайте подпрограмму и поместите в нее все, что было в подпрограмме кнопки

private void DoSharedRoutine(){ // do something }

Шаг 2: иметь общую процедуру вызова обработчика кнопки

private void Login_Click(object sender, System.Windows.RoutedEventArgs e)
    {
        DoSharedRoutine();
    }

Шаг 3: у вас есть обработчик нажатия клавиш вашей панели, содержащий вашу кнопку, вызов общей процедуры

private void MyGrid_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
     {
         if (e.Key == Key.Enter) DoSharedRoutine();
     }
0 голосов
/ 28 мая 2010

Проблема была вызвана неправильным типом GetDefaultButton.Это должно было быть набрано как Button, например, используя:

    public static Button GetDefaultButton(UIElement obj)
    {
        return (Button)obj.GetValue(DefaultButtonProperty);
    }

вместо

    public static DefaultButtonService GetDefaultButton(UIElement obj)    
    {    
        return (DefaultButtonService)obj.GetValue(DefaultButtonProperty);    
    } 

работает, как ожидалось.* Марк

...