C# 如何创建全局按钮并根据WPF/C中的当前可见视图动态附加不同的处理程序?

C# 如何创建全局按钮并根据WPF/C中的当前可见视图动态附加不同的处理程序?,c#,wpf,xaml,C#,Wpf,Xaml,我有一个WPF项目,有许多视图,每个视图有8个页脚按钮。页脚按钮触发属于视图的方法 我希望全局定义页脚按钮一次,并根据当前视图附加不同的单击侦听器 下面是一个更清楚的例子: 页脚按钮在(父)主窗口中创建。如果我导航到View1,第一个按钮将显示标签“Say Hello”,如果单击,它将显示消息“Hello”。如果我导航到View2,第一个按钮将显示标签“说再见”,如果单击,它将显示消息“再见” 我该怎么做?什么是好方法 提前谢谢你 此示例使用界面和带有按钮的用户控件(此处仅3个)。 Wind

我有一个WPF项目,有许多视图,每个视图有8个页脚按钮。页脚按钮触发属于视图的方法

我希望全局定义页脚按钮一次,并根据当前视图附加不同的单击侦听器

下面是一个更清楚的例子:

页脚按钮在(父)主窗口中创建。如果我导航到View1,第一个按钮将显示标签“Say Hello”,如果单击,它将显示消息“Hello”。如果我导航到View2,第一个按钮将显示标签“说再见”,如果单击,它将显示消息“再见”

我该怎么做?什么是好方法


提前谢谢你

此示例使用界面和带有按钮的用户控件(此处仅3个)。 Window1和Window2正在实现该接口。DataContext绑定到用户控件ButtonData属性

每个按钮在标记属性中都有一个索引。按钮单击事件处理程序对于所有按钮都是通用的,但是您可以为每个按钮定义一个事件处理程序

不要忘记并更改xaml中的名称空间

接口IViewButtons.cs

public interface IViewButtons
{
    List<string> ButtonNames { get; set; }
    void Button_Click(object sender, RoutedEventArgs e);
}
MainWindow.xaml

<Window x:Class="WpfApp11.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp11"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <StackPanel Orientation="Horizontal">
            <Button x:Name="BtnView1" Content="View 1" Click="BtnView1_Click" VerticalAlignment="Top" Margin="5"/>
            <Button x:Name="BtnView2" Content="View 2" Click="BtnView2_Click" VerticalAlignment="Top" Margin="5"/>
        </StackPanel>
    </Grid>
</Window>
<Window x:Class="WpfApp11.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp11"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <StackPanel Orientation="Horizontal">
            <Button x:Name="BtnView1" Content="View 1" Click="BtnView1_Click" VerticalAlignment="Top" Margin="5"/>
            <Button x:Name="BtnView2" Content="View 2" Click="BtnView2_Click" VerticalAlignment="Top" Margin="5"/>
        </StackPanel>

        <StackPanel Grid.Row="1" Orientation="Horizontal">
            <Button Content="{Binding ButtonNames[0]}" Tag="0" Click="YourButtons_Click" Margin="5"/>
            <Button Content="{Binding ButtonNames[1]}" Tag="1" Click="YourButtons_Click" Margin="5"/>
            <Button Content="{Binding ButtonNames[2]}" Tag="2" Click="YourButtons_Click" Margin="5"/>
        </StackPanel>

    </Grid>
</Window>
Window1.xaml

<Window x:Class="WpfApp11.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp11"
        mc:Ignorable="d"
        Title="Window1" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <local:YourButtons Grid.Row="1" ButtonData="{Binding}"/>
    </Grid>
</Window>

Window1.xaml.cs

public partial class Window1 : Window, IViewButtons
{
    public Window1()
    {
        DataContext = this;
        InitializeComponent();
    }

    void IViewButtons.Button_Click(object sender, RoutedEventArgs e)
    {
        Button btn = (Button)sender;

        if (int.Parse(btn.Tag.ToString()) == 0)
            MessageBox.Show("Hello");
        else
            MessageBox.Show("Btn " + btn.Tag + " pressed");
    }

    public List<string> ButtonNames { get; set; } = new List<string>()
        {
            "Say Hello",
            "Btn 2",
            "Btn 3"
        };
}
公共部分类窗口1:窗口,IViewButtons
{
公共窗口1()
{
DataContext=this;
初始化组件();
}
无效IViewButtons.按钮单击(对象发送器,路由EventTargets e)
{
按钮btn=(按钮)发送器;
if(int.Parse(btn.Tag.ToString())==0)
MessageBox.Show(“你好”);
其他的
MessageBox.Show(“Btn”+Btn.Tag+“按下”);
}
公共列表按钮名称{get;set;}=new List()
{
“打招呼”,
“Btn 2”,
“Btn 3”
};
}
Window2.xaml

<Window x:Class="WpfApp11.Window2"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp11"
        mc:Ignorable="d"
        Title="Window1" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <local:YourButtons Grid.Row="1" ButtonData="{Binding}"/>
    </Grid>
</Window>

Window2.xaml.cs

public partial class Window2 : Window, IViewButtons
{
    public Window2()
    {
        DataContext = this;
        InitializeComponent();
    }

    void IViewButtons.Button_Click(object sender, RoutedEventArgs e)
    {
        Button btn = (Button)sender;

        if (int.Parse(btn.Tag.ToString()) == 0)
            MessageBox.Show("Goodbye");
        else
            MessageBox.Show("Btn " + btn.Tag + " pressed");
    }

    public List<string> ButtonNames { get; set; } = new List<string>()
        {
            "Say Goodbye",
            "Btn 2",
            "Btn 3"
        };
}
公共部分类窗口2:窗口,IViewButtons
{
公共窗口2()
{
DataContext=this;
初始化组件();
}
无效IViewButtons.按钮单击(对象发送器,路由EventTargets e)
{
按钮btn=(按钮)发送器;
if(int.Parse(btn.Tag.ToString())==0)
MessageBox.Show(“再见”);
其他的
MessageBox.Show(“Btn”+Btn.Tag+“按下”);
}
公共列表按钮名称{get;set;}=new List()
{
“说再见”,
“Btn 2”,
“Btn 3”
};
}
编辑: 第2版: 我没注意到你想要主窗口的按钮。因此,此版本在主Windows XAML中有按钮(无需用户控制)。使用相同的接口。Window1和Window2没有XAML,但后面的代码相同

如果用户打开多个窗口,则必须进行处理

MainWindow.xaml

<Window x:Class="WpfApp11.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp11"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <StackPanel Orientation="Horizontal">
            <Button x:Name="BtnView1" Content="View 1" Click="BtnView1_Click" VerticalAlignment="Top" Margin="5"/>
            <Button x:Name="BtnView2" Content="View 2" Click="BtnView2_Click" VerticalAlignment="Top" Margin="5"/>
        </StackPanel>
    </Grid>
</Window>
<Window x:Class="WpfApp11.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp11"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <StackPanel Orientation="Horizontal">
            <Button x:Name="BtnView1" Content="View 1" Click="BtnView1_Click" VerticalAlignment="Top" Margin="5"/>
            <Button x:Name="BtnView2" Content="View 2" Click="BtnView2_Click" VerticalAlignment="Top" Margin="5"/>
        </StackPanel>

        <StackPanel Grid.Row="1" Orientation="Horizontal">
            <Button Content="{Binding ButtonNames[0]}" Tag="0" Click="YourButtons_Click" Margin="5"/>
            <Button Content="{Binding ButtonNames[1]}" Tag="1" Click="YourButtons_Click" Margin="5"/>
            <Button Content="{Binding ButtonNames[2]}" Tag="2" Click="YourButtons_Click" Margin="5"/>
        </StackPanel>

    </Grid>
</Window>

MainWindow.xaml.cs

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

    private void BtnView1_Click(object sender, RoutedEventArgs e)
    {
        Window1 window1 = new Window1();
        window1.Show();
    }

    private void BtnView2_Click(object sender, RoutedEventArgs e)
    {
        Window2 window2 = new Window2();
        window2.Show();
    }
}
public partial class MainWindow : Window, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public MainWindow()
    {
        DataContext = this;
        InitializeComponent();
    }

    //Bound to the buttons content
    public List<string> ButtonNames
    {
        get { return _buttonNames; }
        set 
        { 
            _buttonNames = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ButtonNames)));
        }
    }
    private List<string> _buttonNames;

    //Contains the current Window, used for accessing the windows implementation of IViewButtons
    IViewButtons currentWindow;

    private void BtnView1_Click(object sender, RoutedEventArgs e)
    {
        Window1 window1 = new Window1();
        currentWindow = window1;
        ButtonNames = currentWindow.ButtonNames;
        window1.Show();
    }

    private void BtnView2_Click(object sender, RoutedEventArgs e)
    {
        Window2 window2 = new Window2();
        currentWindow = window2;
        ButtonNames = currentWindow.ButtonNames;
        window2.Show();
    }

    private void YourButtons_Click(object sender, RoutedEventArgs e)
    {
        //Forwarding the event to the windows event handler
        currentWindow.Button_Click(sender, e);
    }
}
public分部类主窗口:窗口,INotifyPropertyChanged
{
公共事件属性更改事件处理程序属性更改;
公共主窗口()
{
DataContext=this;
初始化组件();
}
//绑定到按钮内容
公共列表按钮
{
获取{return\u buttonNames;}
设置
{ 
_按钮名称=值;
PropertyChanged?.Invoke(这是新的propertychangedventargs(nameof(ButtonNames));
}
}
私有列表按钮名称;
//包含当前窗口,用于访问IViewButtons的windows实现
IViewButtons当前窗口;
私有无效BtnView1_单击(对象发送者,路由目标e)
{
Window1 Window1=新的Window1();
currentWindow=window1;
ButtonNames=currentWindow.ButtonNames;
window1.Show();
}
私有无效BtnView2_单击(对象发送者,路由目标e)
{
Window2 Window2=新的Window2();
currentWindow=window2;
ButtonNames=currentWindow.ButtonNames;
window2.Show();
}
私有作废按钮\u单击(对象发送者,路由目标)
{
//将事件转发到windows事件处理程序
当前窗口。按钮单击(发送者,e);
}
}

Hi@RolandJS,非常感谢。我可以很容易地适应我的——稍微复杂一点的——情况,它就像一种魅力。非常感谢,并致以最良好的问候。