5

几个月来,我一直在我的 SL 3 应用程序中成功使用David Justices 默认按钮示例。此方法基于附加属性。

升级到 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

该问题是由键入错误的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 回答
0

这是按下回车键时连接默认按钮的简单方法:

出于安全原因,silverlight 不会让您直接在代码中调用按钮处理程序,因此我们必须创建一个可以调用的新例程,然后让按钮处理程序和表单 keydown 处理程序都调用此例程。

第 1 步:创建一个例程并将按钮例程具有的所有内容放入其中

private void DoSharedRoutine(){ // do something }

第 2 步:让按钮处理程序调用共享例程

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

第 3 步:让包含按钮的面板的 keydown 处理程序调用共享例程

private void MyGrid_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
     {
         if (e.Key == Key.Enter) DoSharedRoutine();
     }
于 2012-12-20T12:12:33.003 回答