App.xaml中MainWindow.xaml.cs中的Click-Event

时间:2019-02-14 08:02:05

标签: c# wpf xaml

所以我想将一些东西从MainWindow.xaml外包给App.xaml,例如:

<Application x:Class="SVGTesting.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <DataTemplate DataType="{x:Type ContentControl}" x:Key="Test1">
                <StackPanel Orientation="Horizontal">
                    <Button Content="Button1" Click="Button_Click" x:Name="Button1"/>
                    <Button Content="Button2" Click="Button_Click" x:Name="Button2"/>
                </StackPanel>
            </DataTemplate>
        </ResourceDictionary>
    </Application.Resources>
</Application>

在MainWindow.xaml中,我有类似的内容

<ContentControl ContentTemplate="{StaticResource Test1}"/>

但是现在VS说我不能使用函数“ Button_Click”,因为它不在App.xaml的代码后面。那么如何在App.xaml中从MainWindow调用此函数?

有什么办法吗?我不想要MVVM或Command之类的答案。如果无法解决,那么不幸的是WPF对我没用。

谢谢。

2 个答案:

答案 0 :(得分:0)

您无法做到。参见MSDN documentation for Code-Behind

  

您编写的事件处理程序必须是由   x:Class标识的名称空间中的局部类。 您不能   限定事件处理程序的名称以指示XAML处理器执行以下操作:   在不同的类范围内查找该处理程序。您也不能使用   静态方法作为事件处理程序。

在WPF中,您可以改用behaviors

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
<Button Content="btnWithBehavior">
    <i:Interaction.Behaviors>
        <local:HandleButtonClick/>
    </i:Interaction.Behaviors>
</Button>

public class HandleButtonClick : Behavior<Button>
{
    protected override void OnAttached()
    {
        base.OnAttached();

        AssociatedObject.Click += AssociatedObject_Click; ;
    }
    private void AssociatedObject_Click(object sender, RoutedEventArgs e)
    {
        //Move your MainWindow.Button_Click here;
    }
    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.Click -= AssociatedObject_Click;
    }
}

答案 1 :(得分:0)

这不是最简单的事情,因为WPF希望事情以自己的方式完成。但是,从最简单到最困难的选择很少。

1。什么也不要做

最简单的方法是将数据模板保留在MainWindow.xaml中。

2。使用命令代替事件处理程序

您当前具有如下定义的事件处理程序:

<Button Content="Button1" Click="Button_Click"

“ More-WPF方式”将用具有以下繁琐语法的命令替换Click的事件处理程序:

        <Button Content="Test" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.OnClickCommand}"></Button>

然后在MainWindow中定义命令:

    public ICommand OnButtonClick
    {
        get
        {
            return new Command(() =>
            {
                this.Text.Text = "Updated";
            });
        }
    }

3。在App.xaml.cs中定义事件处理程序,并使用其路由事件处理程序

我不建议这样做,因为它会使保持同步变得很累,但是有可能。在App.xaml.cs中创建事件处理程序:

public partial class App : Application
{
    private void Button_Click(object sender, RoutedEventArgs e)
    {

    }
}

然后使用发送方访问MainWindow实例并调用其方法:

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        var mainWindow = (MainWindow)Window.GetWindow((DependencyObject)sender);

        mainWindow.DoWork();
    }

在我的第二个示例中,命令的定义如下:

    public class Command : ICommand
    {
        public delegate void ICommandOnExecute();
        private ICommandOnExecute _execute;

        public event EventHandler CanExecuteChanged;

        public Command(ICommandOnExecute onExecuteMethod)
        {
            _execute = onExecuteMethod;
        }

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public void Execute(object parameter)
        {
            _execute?.Invoke();
        }
    }