访问在运行时创建的控件

问题描述 投票:1回答:2

我是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             
    }
}
c# wpf wpf-controls
2个回答
0
投票

最简单的方法是在字段中存储对按钮的引用:

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)
        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             
        _newBtn.Content = "Test2"; 
    }
}

如果要存储多个控件,请使用字典或列表。


0
投票

您在这里所做的一些复杂操作并不立即显而易见。其中之一是您不能仅仅定义一些处理程序,它就会起作用。您还必须订阅该事件。这是您需要插入事件的委托。

[像电器一样,在发生任何事情之前,都需要先将其插入。

这里有一些标记和代码来探索正在发生的事情。

因此,我可以看到将使用添加内容的列表框的消息。这些将显示为消息列表。

    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旋转她并单击按钮。

有一个惊喜等着你。

没有来自鼠标的消息。

这是因为设计该按钮是为了单击而不是按下鼠标并向上移动鼠标。ButtonBase中的代码可以处理某些鼠标事件,并且由于它可以处理鼠标事件,因此处理程序将不会触发。


因此,我们希望可以解释一些有关事件的内容。

尽管有些事情我也要提到。

几乎所有wpf开发都使用MVVM,并将命令绑​​定到按钮的command属性,而不是完全使用事件。

[添加动态内容通常也不是这样的代码。

有很多选项,包括数据模板。首先使用称为viewmodel的方法,这种情况非常普遍。

您还可以通过将xaml作为字符串转换为控件来构建UI。这是构建UI的推荐方法,当您不能使用样式或模板时,UI必须是动态的。对您来说,现在研究这些东西为时过早,但仅供参考https://social.technet.microsoft.com/wiki/contents/articles/28797.wpf-dynamic-xaml.aspx

© www.soinside.com 2019 - 2024. All rights reserved.