WPF C# пользовательский элемент управления с 2 или более кнопками - PullRequest
1 голос
/ 09 июля 2020

Извините, если об этом спрашивали раньше, и я потратил около недели, пытаясь найти аналогичный вопрос, чтобы указать мне правильное направление. Я обучаю себя C# с помощью WPF, XAML и c и играю с пользовательскими элементами управления. Я сделал простое приложение с пользовательским элементом управления для загрузки поверх других windows или пользовательских элементов управления. Рассматриваемый U C имеет две кнопки, и мне нужно перейти к событиям щелчка для каждой кнопки в главном окне после загрузки элемента управления. В главном окне есть кнопка, которая загружает элемент управления.

Благодаря некоторым исследованиям мне удалось найти решение от пользователя SWilko ({ ссылка }), но я не могу понять его для каждую кнопку по отдельности (нажмите кнопку a и покажите «нажато btn a», нажмите кнопку b и покажите «нажатую кнопку b»). Я пытался позвонить отправителю по имени, и это тоже не сработает. Мне кажется, что я близок с помощью ответа SWilko, но застрял.

Вот код до сих пор: Basi c пользовательский элемент управления загрузкой основного экрана

    <Window x:Class="UCBTN_TEST.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:UCBTN_TEST"
            mc:Ignorable="d"
            Title="MainWindow" Height="450" Width="435">
        <Grid>
            <Button Content="Load Button" HorizontalAlignment="Left" Margin="18,23,0,0" VerticalAlignment="Top" Width="74" Click="Button_Click"/>
            <Grid x:Name="GridLoad" HorizontalAlignment="Left" Height="300" Margin="120,23,0,0" VerticalAlignment="Top" Width="300" Background="#FFF1CBCB"/>
    
        </Grid>
    </Window>
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace UCBTN_TEST
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
    
            private void Button_Click(object sender, RoutedEventArgs e)
            {
                GridLoad.Children.Clear();
                GridLoad.Children.Add(new WindowControl());
            }
        }
    }

Пользовательский элемент управления кнопки

    <UserControl x:Name="UCMain" x:Class="UCBTN_TEST.Controls.ButtonControl"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:local="clr-namespace:UCBTN_TEST.Controls"
                 mc:Ignorable="d" d:DesignWidth="300" Height="40.333">
        
        <Grid Background="#FFE7EEA7">
            <Button x:Name="ButtonA" Content="Button A" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="75" Click="ButtonA_Click" Background="Red"/>
            <Button x:Name="ButtonB" Content="Button B" HorizontalAlignment="Left" Margin="215,10,0,0" VerticalAlignment="Top" Width="75" Click="ButtonA_Click" Background="Green"/>
        </Grid>
    </UserControl>
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace UCBTN_TEST.Controls
    {
        /// <summary>
        /// Interaction logic for ButtonControl.xaml
        /// </summary>
        public partial class ButtonControl : UserControl
        {
            public ButtonControl()
            {
                InitializeComponent();
            }
    
            private void ButtonA_Click(object sender, RoutedEventArgs e)
            {
                RaiseEvent(new RoutedEventArgs(ClickEvent1, this));
            }
    
            public static readonly RoutedEvent ClickEvent1 = EventManager.RegisterRoutedEvent("Click", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(ButtonControl));
    
            public event RoutedEventHandler Click
            {
                add { AddHandler(ClickEvent1, value); }
                remove { RemoveHandler(ClickEvent1, value); }           
            }
        }
    }

Второй пользовательский элемент управления, который в конечном итоге будет иметь некоторые другие элементы управления, если кнопки будут работать правильно. Но кнопка U C будет загружаться поверх простых функций кнопки, связанных с WindowControl.

    <UserControl
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:local="clr-namespace:UCBTN_TEST"
                 xmlns:Controls="clr-namespace:UCBTN_TEST.Controls" x:Class="UCBTN_TEST.WindowControl"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
    
        <Grid Background="#FFE7CFEE">
            <Controls:ButtonControl HorizontalAlignment="Left" Height="37" VerticalAlignment="Top" Width="300" Click="Click1"/>
        </Grid>
    
    </UserControl>

Я понимаю скрытый код и почему это происходит. Моя проблема в том, что мне нужно, чтобы кнопки были уникальными по своим событиям. Я пробовал звонить по отправителю и имени, и это просто убивает событие вместе.

    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    using UCBTN_TEST.Controls;
    
    namespace UCBTN_TEST
    {
        /// <summary>
        /// Interaction logic for WindowControl.xaml
        /// </summary>
        public partial class WindowControl : UserControl
        {
    
            public WindowControl()
            {
                InitializeComponent();            
            }
    
            private void Click1(object sender, RoutedEventArgs e)
            {
                
                MessageBox.Show("This triggers both");
                
            }
        }
    }

1 Ответ

1 голос
/ 09 июля 2020

Я собирался добавить кучу комментариев, но на самом деле это своего рода ответ на вопрос, и есть что объяснить. какая кнопка была нажата. Из этого есть исключения. Например, если вы создавали экранную клавиатуру. Причина в другом, потому что его цель может быть инкапсулирована. Пользователь нажимает кнопку с буквой «А». Независимо от того, какое текстовое поле находится в фокусе, следует отправить символ «A». Они нажимают кнопку, показывающую "B", и аналогично должна быть отправлена ​​"B". Эта функция может быть инкапсулирована в элемент управления.

Как бы то ни было, у вас есть две кнопки.

Вы помещаете их в пользовательский элемент управления и инкапсулируете их.

Делая это, вы создал границу.

Затем возникает сложность - на что щелкнули?

Пользовательское управление также не особенно удобно для повторного использования. Если вы добавите два, то будет две кнопки A и две кнопки B. Вы можете улучшить это с помощью настраиваемых аргументов события в настраиваемом перенаправленном событии и свойства зависимости в вашем пользовательском элементе управления. Передайте некоторый идентификатор пользовательского элемента управления вместе с тем, какая кнопка была нажата.

Однако это было бы необычным способом работы. Я редко встречал пользовательские перенаправленные события, используемые в коммерческих приложениях.

В целом, я бы сказал, что пользовательское управление в основном добавляет сложности.

Допустим, вы хотели иметь 20 наборов по 2 кнопки.

Или 20 наборов по 5 радиокнопок для набора вопросов с несколькими вариантами ответов.

Чтобы сделать это, используйте элемент управления элементами и шаблон для нескольких элементов управления. Один шаблон, дающий 2 кнопки (или вопрос с текстовым блоком и 5 радиокнопок для ответов) на строку.

Событие щелчка уже является перенаправленным событием и всплывет в окно. Вы также можете удалить свое настраиваемое перенаправленное событие и обработчик из usercontrol ... и usercontrol. Просто нажмите кнопку мыши в окне.

Код:

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

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        var btn = e.OriginalSource as Button;
        if(btn == null)
        {
            return;
        }

        MessageBox.Show($"Button clicked was {btn.Tag}");
    }

Разметка:

    ButtonBase.Click="Button_Click"
    Title="MainWindow" 
        >
    <Grid>
        <StackPanel>
            <Button x:Name="ButtonA" Content="Button A" Tag="A" Background="Red"/>
            <Button x:Name="ButtonB" Content="Button B" Tag="B" Background="Green"/>
        </StackPanel>
    </Grid>
    </Window>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...