Доступ к элементу управления, созданному во время выполнения - PullRequest
1 голос
/ 15 февраля 2020

Я новичок в c# и wpf.

Если я создаю элемент управления в XAML, я могу получить доступ к его свойствам в любом месте моего кода. Однако, если я создаю элемент управления во время выполнения, он отображается как null, когда я пытаюсь получить доступ к нему вне метода, который он был создан.

public partial class MainWindow : Window
{

    public MainWindow()
    {
        InitializeComponent();
        Button newBtn = new Button();

        newBtn.Content = "Test";
        newBtn.Name = "btnTest";
        spTest.Children.Add(newBtn);

    }

    private void WPFButton_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
         //I want to access the button called btnTest and display the name of the button             
    }
}

Ответы [ 2 ]

1 голос
/ 15 февраля 2020

Есть несколько сложностей в том, что вы делаете здесь, которые не сразу очевидны. Одним из них является то, что вы не можете просто определить какой-либо обработчик, и он будет работать. Вы также должны подписаться на это событие. Это делегат, которого вы как бы подключаете к событию.

Как электрический прибор, вам нужно подключить его, прежде чем что-либо произойдет.

Вот некоторая разметка и код для изучения что происходит.

Чтобы я мог видеть сообщения, я буду использовать список, в который я буду добавлять элементы. Они будут отображаться в виде списка сообщений.

    Title="MainWindow" Height="450" Width="800"
    Button.Click="Window_Button_Click">
    <Grid Name="agrid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <ListBox Name="lb"
                 Grid.Column="1"/>
    </Grid>

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

https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/routed-events-overview

Затем я собираюсь динамически добавить кнопку. По умолчанию это будет столбец 0 сетки и появится слева.

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

Я также подписываюсь еще на два события кнопки.

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        Button newBtn = new Button();

        newBtn.Content = "Test";
        newBtn.Name = "btnTest";
        agrid.Children.Add(newBtn);
        newBtn.MouseUp += NewBtn_MouseUp;
        newBtn.PreviewMouseDown += NewBtn_PreviewMouseDown;
    }

    private void NewBtn_PreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        Button btn = sender as Button;
        string theName = btn?.Name ?? "Something was Preview Mouse Downed but I don't know what";
        lb.Items.Add($"Button PREVIEW MouseUp {theName}");
    }

    private void NewBtn_MouseUp(object sender, MouseButtonEventArgs e)
    {
        Button btn = sender as Button;
        string theName = btn?.Name ?? "Something was Mouse Upped but I don't know what";
        lb.Items.Add($"Button MouseUp {theName}");
    }

    private void Window_Button_Click(object sender, RoutedEventArgs e)
    {
        Button btn = e.OriginalSource as Button;
        string theName = btn?.Name ?? "Something was CLICKED in the window but I don't know what";
        lb.Items.Add($"Window Button Click {theName}");
    }
}

Приведенный выше код довольно быстрый и грязный.

Обратите внимание, что обработчик всплывающих событий интересуется источником источника события, так как он передан по дереву, и отправитель не будет кнопкой.

f5, чтобы раскрутить ее и нажать кнопку.

Там вас ждет сюрприз.

Нет сообщения от mouseup.

Это потому что кнопка предназначена для нажатия, а не mousedown и мыши. Код в ButtonBase работает с некоторыми событиями мыши, и, поскольку он обрабатывает их, ваш обработчик не будет запускаться.


Так что, мы надеемся, кое-что объяснено в событиях.

Есть Однако следует упомянуть несколько вещей.

Почти все разработки wpf используют MVVM и привязывают команду к свойству команды кнопки, а не используют события вообще.

Добавление динамич c содержимое также обычно не выполняется в коде, подобном этому.

Существует ряд опций, которые включают шаблоны данных. Это очень часто встречается в подходе под названием viewmodel.

Вы также можете создать пользовательский интерфейс, переведя xaml в виде строки в элементы управления. Это рекомендуемый способ создания пользовательского интерфейса, который должен быть динамическим c, когда вы не можете использовать стили или шаблоны. Вам, наверное, еще рано вникать в эти вещи, но к вашему сведению https://social.technet.microsoft.com/wiki/contents/articles/28797.wpf-dynamic-xaml.aspx

0 голосов
/ 15 февраля 2020

Самый простой способ - сохранить ссылку на кнопку в поле:

public partial class MainWindow : Window 
{
    private Button _newBtn;

    public MainWindow()
    {
        InitializeComponent();
        _newBtn = new Button();

        _newBtn.Content = "Test";
        _newBtn.Name = "btnTest";  // < the name is not needed, because you already have a reference. (so you don't have to use FindControl)
        // and if you want to register the click event.
        _newBtn.Click += Button_Click;
        spTest.Children.Add(_newBtn);
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        MessageBox.Show("Button clicked");
    }

    private void WPFButton_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        //I want to access the button called btnTest and display the name of the button             
        _newBtn.Content = "Test2"; 
    }
}

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

...