XAML中静态函数作为事件处理程序

4
我正在使用这段代码来模拟在我的Silverlight应用程序中的tab键功能。
我希望避免多次编写此函数,因为它需要在应用程序中的许多文本框上使用。我已经创建了一个静态类。
public static class TabInsert
{
    private const string Tab = "    ";
    public static void textBox_KeyDown(object sender, KeyEventArgs e)
    {
        TextBox textBox = sender as TextBox;
        if (e.Key == Key.Tab)
        {
            int selectionStart = textBox.SelectionStart;
            textBox.Text = String.Format("{0}{1}{2}",
                    textBox.Text.Substring(0, textBox.SelectionStart),
                    Tab,
                    textBox.Text.Substring(textBox.SelectionStart + textBox.SelectionLength, (textBox.Text.Length) - (textBox.SelectionStart + textBox.SelectionLength))
                    );
            e.Handled = true;
            textBox.SelectionStart = selectionStart + Tab.Length;
        }
    } 
}

这样我就可以从各个地方访问它,就像这样 textBox.KeyDown += TabInsert.textBox_KeyDown;

在XAML中有没有办法做到这一点?

2个回答

6
您可以创建一个Behavior(System.Windows.Interactivity命名空间),轻松附加到文本框上。在OnAttached()重写中订阅事件,像您一样进行处理,并在OnDetaching()中取消订阅。
类似于下面的示例:
public class TabInsertBehavior : Behavior<TextBox>
{
    /// <summary>
    /// Called after the behavior is attached to an AssociatedObject.
    /// </summary>
    /// <remarks>
    /// Override this to hook up functionality to the AssociatedObject.
    /// </remarks>
    protected override void OnAttached()
    {
        base.OnAttached();
        this.AssociatedObject.KeyDown += textBox_KeyDown;
    }

    private const string Tab = "    ";
    public static void textBox_KeyDown(object sender, KeyEventArgs e)
    {
        TextBox textBox = sender as TextBox;
        if (e.Key == Key.Tab)
        {
            int selectionStart = textBox.SelectionStart;
            textBox.Text = String.Format("{0}{1}{2}",
                    textBox.Text.Substring(0, textBox.SelectionStart),
                    Tab,
                    textBox.Text.Substring(textBox.SelectionStart + textBox.SelectionLength, (textBox.Text.Length) - (textBox.SelectionStart + textBox.SelectionLength))
                    );
            e.Handled = true;
            textBox.SelectionStart = selectionStart + Tab.Length;
        }
    } 

    /// <summary>
    /// Called when the behavior is being detached from its AssociatedObject, but before it has actually occurred.
    /// </summary>
    /// <remarks>
    /// Override this to unhook functionality from the AssociatedObject.
    /// </remarks>
    protected override void OnDetaching()
    {
        base.OnDetaching();
        this.AssociatedObject.KeyDown -= textBox_KeyDown;
    }
}

3
在您的XAML代码中,您需要输入以下内容:<TextBox><i:Interaction.Behaviors>local:TabInsertBehavior/</i:Interaction.Behaviors></TextBox>。 - Filip Skakun
我完全同意xyzzer的看法 - 附加的行为是一个很好的解决方法。(另见[如何在代码后台中附加行为] (http://geekswithblogs.net/SilverBlog/archive/2009/09/22/behaviors-how-to-attach-behavior-in-code-behind-silverlight-3.aspx)) - DmitryG
我也同意,但这只会构建一个相当糟糕的XAML,而我最不想要的就是这个,因为有很多文本框需要这个功能... - Ivan Crojach Karačić
你可以注册一个附加的依赖属性,它可以完成与行为相同的功能。实际上,出于你提到的确切原因,这种方法会更好。只需定义一个类,例如TextBoxExtensions,然后执行类似DependencyProperty.RegisterAttached("AutoTabs", typeof(bool), typeof(TextBoxExtensions), new PropertyMetadata(null, OnAutoTabsChanged))的操作,当它被设置为true时,在OnAutoTabsChanged中订阅事件,当它被设置为false时取消订阅。然后,你可以将其用作属性,例如<TextBox ext:TextBoxExtensions.AutoTabs="true"/>。 - Filip Skakun

6

不幸的是,在XAML中没有直接的方法来实现这一点。您在代码后台编写的事件处理程序必须是实例方法,不能是静态方法。这些方法必须由部分类定义,该部分类位于由x:Class标识的CLR命名空间中。您不能限定事件处理程序的名称以指示XAML处理器在不同的类范围中查找事件处理程序进行事件连接。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接