6

如何收听我的 WPF 应用程序中的所有按钮点击。也许包括一些复选框左右,但理想情况下我不想有额外的事件处理程序。

我想收集初始统计数据以了解人们如何使用我们的应用程序。我想确保我不会干扰任何其他事件处理功能。

在应用程序中,新窗口正在使用自己的按钮打开和关闭,所以我不能静态地做到这一点。

或者,是否有任何常用方法可以从 WPF 应用程序收集使用情况统计信息。

4

5 回答 5

7

如何收听我的 WPF 应用程序中的所有按钮点击?

您可以使用EventManager将事件挂钩到一个类型的所有对象:

EventManager.RegisterClassHandler(typeof(Button), Button.ClickEvent, new RoutedEventHandler(Button_Click));

private void Button_Click(object sender, RoutedEventArgs e)
{

}

在应用程序中,新窗口正在使用自己的按钮打开和关闭,所以我不能静态地做到这一点。

如果您在 WPF 中创建这些窗口,则可以挂钩到窗口事件,例如 Closed、Sizechanged 和 Got/LostFocus()。如果这些 Windows 不是基于 WPF/Winform,您可以使用ShellHook

于 2013-07-18T12:47:46.277 回答
2

您可以使用以下样式:

.xaml

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <StackPanel.Resources>
            <Style TargetType="Button">
                <EventSetter Event="Click" Handler="Button_Click" />
            </Style>
        </StackPanel.Resources>
        <Button x:Name="b1" Click="Button1_Click" Content="1" />
        <Button x:Name="b2" Click="Button2_Click" Content="2" />
        <Button Content="other" />
    </StackPanel>
</Window>

xml.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Console.WriteLine("some button");
    }

    private void Button1_Click(object sender, RoutedEventArgs e)
    {
        Console.WriteLine("button1");
    }

    private void Button2_Click(object sender, RoutedEventArgs e)
    {
        Console.WriteLine("button2");
    }
}

当放入 app.xaml 时,该样式可以是应用程序范围的。

于 2013-07-18T12:54:18.860 回答
0

您应该使用命令来处理按钮单击事件。每个窗口都有 CommandBinding 实例,在它们的 Execute 处理方法中,您可以将有关当前按钮使用情况的信息发送到某个类的某个静态单例实例中,该实例将为您保存结果。命令和命令绑定不是必需的,但如果您使用的是 MVVM 模式,请尝试使用它们。而不是静态单例使用自定义服务。

于 2013-07-18T12:45:23.180 回答
0

您可以使用每个窗口的 Window_Loaded 事件,并遍历您的 VisualTree,找到所有按钮并注册您的附加通用处理程序:

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        //Capture all buttons of this form.
        findButtons(this);
    }

    public void findButtons(FrameworkElement parent)
    {
        int childCount = VisualTreeHelper.GetChildrenCount(parent);

        for(int i=0; i<childCount; i++){
            var child = VisualTreeHelper.GetChild(parent,i);

            if (child is Button){
                  ((Button)child).Click += All_Button_Click;
            }

            var frameworkElement = child as FrameworkElement;
            findButtons(frameworkElement);
        }
    }

    private void All_Button_Click(object sender, RoutedEventArgs e)
    {
        MessageBox.Show("Generic Handler");
    }

您的所有按钮都可以保持原样,并拥有自己的自定义事件处理程序。您还可以在主窗口上使用处理程序来覆盖所有表单等。

于 2013-07-18T13:37:56.733 回答
0

嗨,我有一个想法,我不知道它是否完美。

public partial class App : Application
{
    //Create list of string in your App class this will contain the names of button in order they are clicked
    public static List<string> ButtonNames = new List<string>();
}

创建一个继承 Button 类的自定义 Button 类,并在您的应用程序中使用此 CustomButton 类而不是 Button 并重载按钮类的 OnClick 方法并在其中订阅一个事件。这会将按钮名称添加到上面创建的 ButtonNames 列表中

 public class MyButton : Button
{
    private bool isClickEventAttached = false;
    protected override void OnClick()
    {
        if (!isClickEventAttached)
        {
            this.Click += MyButton_Click;
            isClickEventAttached = true;
        }
        //dont forget to do this base.Click() otherwise your 
        //button click event that you will subscribe in your application will not fire
        base.OnClick();
    }

    private void MyButton_Click(object sender, RoutedEventArgs e)
    {
        var button=sender as Button;
        if (button != null)
            App.ButtonNames.Add((button.Name));
    }
}

xml

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:commonControls="clr-namespace:WpfApplication1"
    Title="MainWindow" Height="350" Width="525">
<StackPanel>
    <commonControls:MyButton x:Name="mybutton1" Click="MyButton_Click_1"/>
    <commonControls:MyButton x:Name="mybutton2" Click="MyButton_Click_2"/>
</StackPanel>

。CS

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();  
    }

    private void MyButton_Click_1(object sender, RoutedEventArgs e)
    {

    }

    private void MyButton_Click_2(object sender, RoutedEventArgs e)
    {

    }
}

我希望你能明白我想说什么

于 2013-07-18T13:40:58.577 回答