首页 > 解决方案 > WPF 背后的代码 - 如何访问 UI 元素或将其传递给事件处理程序?

问题描述

无论好坏,我只在代码后面构建 WPF UI。我在堆栈面板中有一个按钮和一个文本块。单击该按钮时,会使用一些信息更新 TextBlock。如果我使 TextBlock 成为该类的成员,它将成功运行。然而,仅仅在整个地方声明全局 UI 元素感觉就像是一个简单的出路。有没有办法在 MainWindow() 中实例化 TextBlock 并且仍然可以在按钮单击事件中访问它?

以下伪代码有效:

public partial class MainWindow : Window
{
    public TextBlock myTextBlock;

    public MainWindow()
    {

        StackPanel mainStackPanel = new StackPanel();

        Button myButton = new Button();

        myButton.Click += NewButton_Click();

        mainStackPanel.Children.Add(myTextBlock);

        mainStackPanel.Children.Add(myButton);

        Content = mainStackPanel;

    }

    private void NewGridButton_Click(object sender, RoutedEventArgs e)
    {
        myTextBlock.Text = "Some Text"
    }

}

但是,我很好奇这些方面的事情是否也是可能的:


public partial class MainWindow : Window```
{
    public MainWindow()
    {

        StackPanel mainStackPanel = new StackPanel();

        Button myButton = new Button();

        TextBlock myTextBlock = New TextBlock();

        myButton.Click += NewButton_Click();

        mainStackPanel.Children.Add(myTextBlock);

        mainStackPanel.Children.Add(myButton);

        Content = mainStackPanel;

    }

    private void NewGridButton_Click(object sender, RoutedEventArgs e)
    {
        //Somehow Access the myTextBlock from MainWindow here in order to set the text?

        myTextBlock.Text = "Some Text" // This would not compile.
    }

}

为简洁起见,此处的代码仅作为示例,并不具备全部功能。预先感谢您提供有关此主题的任何信息。


编辑 - 跟进。这里答案的共识似乎表明我在考虑这个问题。代表我希望使用的 UI 元素的私有类变量似乎是一种普遍接受的(不一定是懒惰的)声明和访问 UI 元素的方式。感谢所有花时间审查和评论的人。

标签: c#wpfuser-interface

解决方案


这是对 WPF 的严重滥用,我怀疑您已经知道这一点。但是,如果您坚持,您可以在创建 TextBlock 时为其命名:

myTextBlock.Name = "MyTextBlock";

然后,您可以随时遍历可视化树来找到它。将此答案中的代码FindChild添加到您的课程中,然后在您的点击处理程序中执行此操作:

private void MyButton_Click(object sender, RoutedEventArgs e)
{
    var textBlock = FindChild<TextBlock>(this, "MyTextBlock");
    textBlock.Text = "Hello World!";
}

如果它只是您需要支持的子控件的动态创建,那么更好的解决方案是为它们创建一个字典:

private Dictionary<string, FrameworkElement> Children = new Dictionary<string, FrameworkElement>();

...然后您将使用唯一标识符将每个控件添加到其中:

TextBlock myTextBlock = new TextBlock();
this.Children["MyTextBlock"] = myTextBlock;

虽然仍然不是在 WPF 中执行此操作的“正确”方式,但至少您不再需要遍历整个树来寻找您所追求的元素:

var textBlock = this.Children["MyTextBlock"] as TextBlock;
textBlock.Text = "Hello World!";

推荐阅读