5

数か月間、私は SL 3 アプリでDavid Justices の Default Button の例をうまく使用してきました。このアプローチは、添付プロパティに基づいています。

SL4 にアップグレードした後、このアプローチは機能しなくなり、XAML 例外が発生します。

不明なパーサー エラー: スキャナー 2148474880

SL4 でこの (または他の) デフォルトのボタン接続動作をうまく使用した人はいますか?

利用可能な新しいクラスを使用して、SL4 でデフォルトのボタン動作を実現する他の方法はありますか?

ありがとう、マーク

4

5 に答える 5

8

私たちにとっての最終的な解決策は、(すべての MVVM パターンのように) ボタンのクリックが発生する前に、バッキング プロパティが更新されないという問題を回避する必要がありました.... 注: peer.SetFocus();

編集: 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>
于 2010-07-09T13:28:20.327 に答える
3

Silverlight 4 でこのような一般的なユース ケースにすぐに使用できるソリューションがあることを本当に望んでいましたが、残念ながら存在しないと思います。

Patrick Cauldwell による別の Default Button 実装があります。彼は添付プロパティも使用しています。

SL 4 アプリケーションでこれをテストしましたが、うまくいくようです。

ここでコードを見つけることができます: http://www.cauldwell.net/patrick/blog/DefaultButtonSemanticsInSilverlightRevisited.aspx

編集: David Justice のコードを微調整して、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>
于 2010-04-29T05:16:33.327 に答える
2

カスタム キー (デフォルトは Enter) を追加のプロパティに設定できるようにすることで、David のアプローチを拡張しました。

    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" ...
于 2010-05-26T14:03:25.660 に答える
0

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();
     }
于 2012-12-20T12:12:33.003 に答える
0

GetDefaultButtonこの問題は、メソッドの型が不適切であることが原因でした。これはButton、たとえば次のように入力する必要があります。

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

それ以外の

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

期待どおりに動作します。

HTH 他の誰か、
マーク

于 2010-05-28T11:09:59.383 に答える