如何从另一个类或窗口访问WPF中的控件

24

我想在WPF的主窗口中访问我的按钮或文本框等控件,但是我无法做到这一点。

在Windows表单应用程序中,这很容易,您可以将该控件的修改器设置为True,并可以从该主窗口的实例访问该控件,但在WPF中,我无法声明一个公共控件。我该怎么做?


你的意思是什么,访问控件? - Arsen Mkrtchyan
可能的解决方案:https://dev59.com/YEvSa4cB1Zd3GeqPhdTU - Mangesh
9个回答

39

要访问另一个WPF窗体中的控件,您需要将该控件声明为public。WPF控件的默认声明是public,但您可以使用以下代码指定它:

<TextBox x:Name="textBox1" x:FieldModifier="public" />

在此之后,您可以在应用程序的所有活动窗口中搜索以查找具有此类控件的窗口:

foreach (Window window in Application.Current.Windows)
{
    if (window.GetType() == typeof(Window1))
    {
       (window as Window1).textBox1.Text = "I changed it from another window";
    }
}

不知道是否是好的实践,但它的效果很好...我正在使用它来从用户控件(使用FirstFloor MUI)更新我的主窗口中的状态栏。 - BENN1TH
在新的类文件中,当我引用System.Windows并使用此foreach循环时,由于没有窗口,它会抛出空引用异常。 - Chandraprakash

6
很遗憾,WPF的基础是数据绑定。使用其他方式会“逆流而上”,是不好的实践,通常编码和理解的复杂度要高出数个数量级。
对于您的问题,如果您有需要在视图之间共享的数据(即使只有一个视图),请创建一个视图模型类,其中包含表示数据的属性,并从您的视图中绑定到这些属性。
在您的代码中,只管理您的视图模型类,不要触及实际的视图及其可视化控件和可视化组合。

5

我发现在WPF中,你必须将Window强制转换为MainWindow。

看起来很复杂,但其实很容易!然而,这可能不是最佳实践。

假设我们有一个标签Label1、一个按钮Button1在MainWindow中,而且你有一个处理与用户界面相关的任何事物的类叫做UI。

我们可以有以下代码:

MainWindow类:

namespace WpfApplication1
{
    public partial class MainWindow : Window
    {
        UI ui = null;
        //Here, "null" prevents an automatic instantiation of the class,
        //which may raise a Stack Overflow Exception or not.
        //If you're creating controls such as TextBoxes, Labels, Buttons... 

        public MainWindow()
        {
            InitializeComponent(); //This starts all controls created with the XAML Designer.
            ui = new UI(); //Now we can safely create an instantiation of our UI class.
            ui.Start();
        }


    }
}

UI 类:

namespace WpfApplication1
{    
public class UI
    {
        MainWindow Form = Application.Current.Windows[0] as MainWindow;
        //Bear in mind the array! Ensure it's the correct Window you're trying to catch.

        public void Start()
        {
            Form.Label1.Content = "Yay! You made it!";
            Form.Top = 0;
            Form.Button1.Width = 50;
            //Et voilá! You have now access to the MainWindow and all it's controls
            //from a separate class/file!
            CreateLabel(text, count); //Creating a control to be added to "Form".
        }

        private void CreateLabel(string Text, int Count)
        {
            Label aLabel = new Label();
            aLabel.Name = Text.Replace(" ", "") + "Label";
            aLabel.Content = Text + ": ";
            aLabel.HorizontalAlignment = HorizontalAlignment.Right;
            aLabel.VerticalAlignment = VerticalAlignment.Center;
            aLabel.Margin = new Thickness(0);
            aLabel.FontFamily = Form.DIN;
            aLabel.FontSize = 29.333;

            Grid.SetRow(aLabel, Count);
            Grid.SetColumn(aLabel, 0);
            Form.MainGrid.Children.Add(aLabel); //Haha! We're adding it to a Grid in "Form"!
        }


    }
}

你的例子是有效的,只是你的代码有点多。代码 MainWindow mainWindow = Application.Current.Windows[0] as MainWindow; bool flag = (bool)mainWindow.chkWriteResults.IsChecked - Saleem

4
var targetWindow = Application.Current.Windows.Cast<Window>().FirstOrDefault(window => window is principal) as principal;
targetWindow .BssAcesso.Background = Brushes.Transparent;

只需从当前窗口调用它的任何控件:

targetWindow.ABUTTON.Background = Brushes.Transparent;

如何在WPF中从一个窗口访问另一个窗口的控件(RichTextBox)?

这篇文章介绍了如何在WPF应用程序中,从一个窗口访问另一个窗口里的控件(RichTextBox)。

3

当我开始学习WPF时,我也曾为此苦恼。然而,我找到了一个很好的解决方法,类似于老式的Win Forms做法(编写VB.NET,抱歉)。在之前所说的基础上,可以直接从模块或不同的类中更改活动窗口对象的属性:

Public Class Whatever
    Public Sub ChangeObjProperties()
        ' Here the window is indexed in case of multiple instances of the same
        ' window could possibly be open at any given time.. otherwise just use 0
        Dim w As MainWindow = Application.Current.Windows(0)
        w.Button1.Content = "Anything"
    End Sub
End Class

在你的代码中调用ChangeObjProperties()之前,你显然需要实例化Whatever

此外,在XAML中关于对象可访问性的命名无需担心。


1

控件的默认声明是非公共、内部和非公共的!

因此,可以从同一程序集中访问控件。如果您想从另一个程序集中访问wpf表单上的控件,则必须使用修改器属性x:FieldModifier="public"或使用Jean提出的方法。


1
只需像这样声明您的控件即可使其公开:
<TextBox x:Name="textBox1" x:FieldModifier="public" />

您可以从另一个控件访问它。


只需为所需的控件设置一个 x:Name,即可立即使用。 - Arthur Nunes
2
如果您使用VB,请将“Public”大写。 - Andrea Antonangeli
默认情况下是公开的。但问题并没有得到解答。 - Ahad aghapour

0
这可能是一个略微不同的答案,但让我们思考一下为什么需要在表单之间传递数据。显然,原因是“可视化”。
使用委托或事件。
没有必要将元素声明为公共元素,只是为了使其可见。只需要能够使用委托在窗口内部有限地转换元素即可。

-1

访问另一个窗口中的任何控件都非常简单。假设要从登录窗口访问MainWindow。以下是步骤:

MainWindow MW = new MainWindow();  //declare the mainwindow
MW.Label1.Content = "Hello world"; //specify what control
MW.ShowDialog();                   //check what happen to that control

良好的编程


1
想象一下我们有两个表单,并且想要更改另一个已创建并打开的表单标签的内容,而不是表单的新实例。 - Ahad aghapour
2
假设你有两个窗体(form1和form2),在form1中有一个文本框并计数,现在你在form2中并想要在运行时获得form1.textbox的值。如果你创建一个新的form1实例,该textbox将具有默认值,但我们不想要默认值。 - Ahad aghapour
1
抱歉误解了,伙计。谢谢。 - Hashim Shubber

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接