简体   繁体   English

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

[英]How can I access a control in WPF from another class or window

I want to access my controls like button or textbox in mainWindow in WPF, but I can't do this.我想在 WPF 的 mainWindow 中访问我的控件,如按钮或文本框,但我不能这样做。

In Windows Form application it's so easy, you can set modifier of that control to True and you can reach that control from an instance of that mainWindow, but in WPF I can't declare a public control.在 Windows 窗体应用程序中,这非常简单,您可以将该控件的修饰符设置为 True,并且您可以从该 mainWindow 的实例访问该控件,但在 WPF 中我无法声明公共控件。 How can I do this?我怎样才能做到这一点?

To access controls in another WPF forms, you have to declare that control as public. 要访问其他WPF表单中的控件,您必须将该控件声明为public。 The default declaration for controls in WPF is public, but you can specify it with this code: WPF中控件的默认声明是public,但您可以使用以下代码指定它:

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

And after that you can search in all active windows in the application to find windows that have control like this: 之后,您可以搜索应用程序中的所有活动窗口,以查找具有以下控件的窗口:

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

Unfortunately, the basics of WPF are data bindings. 不幸的是,WPF的基础是数据绑定。 Doing it any other way is 'going against the grain', is bad practice, and is generally orders of magnitude more complex to code and to understand. 以任何其他方式这样做是“违背谷物”,是不好的做法,并且编码和理解通常更复杂。

To your issue at hand, if you have data to share between views (and even if it's only one view), create a view model class which contains properties to represent the data, and bind to the properties from your view(s). 对于您手头的问题,如果您要在视图之间共享数据(即使它只是一个视图),请创建一个视图模型类,其中包含表示数据的属性,并从视图中绑定到属性。

In your code, only manage your view model class, and don't touch the actual view with its visual controls and visual composition. 在您的代码中,仅管理您的视图模型类,而不是通过其可视控件和可视组合触摸实际视图。

I found that in WPF, you have to cast Window as a MainWindow. 我发现在WPF中,你必须将Window转换为MainWindow。

Looks complicated but it's very easy! 看起来很复杂,但很容易! However, maybe not best practices. 但是,也许不是最佳实践。

Supposing we have a Label1, a Button1 in the MainWindow, and you have a class that deals with anything related to the User Interface called UI. 假设我们在MainWindow中有一个Label1,一个Button1,并且您有一个类来处理与称为UI的用户界面相关的任何事情。

We can have the following: 我们可以有以下内容:

MainWindow Class: 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 Class: 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"!
        }


    }
}

I was also struggling with this when I started WPF. 当我开始使用WPF时,我也在努力解决这个问题。 However, I found a nice way around it similar to the good old fashioned win forms approach (coding VB.NET, sorry). 但是,我找到了一个很好的方法,类似于老式的胜利形式方法(编写VB.NET,对不起)。 Adding on what was said earlier: 添加前面说过的内容:

To directly change properties of objects from a module or a different class for an active window: 要直接更改活动窗口的模块或不同类的对象属性,请执行以下操作:

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

You obviously have to instantiate Whatever before ChangeObjProperties() can be called in your code. 您显然必须在代码中调用ChangeObjProperties()之前实例化Whatever

Also there is no need to worry about naming in XAML regarding object accessibility. 此外,无需担心XAML中有关对象可访问性的命名。

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

just call any control of it from your current window: 只需从当前窗口调用它的任何控件:

targetWindow.ABUTTON.Background = Brushes.Transparent;

How can I access one window's control (richtextbox) from another window in wpf? 如何从wpf中的另一个窗口访问一个窗口的控件(richtextbox)?

Just declare your control like this to make it public: 只需声明您的控件,使其公开:

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

You can then access it from another control. 然后,您可以从另一个控件访问它。

The default declaration of controls is non public, internal and not public! 控件的默认声明是非公开的,内部的而不是公开的!

Access of the controls from within the same assembly is hence allowed. 因此允许从同一组件内访问控件。 If you want to access a control on a wpf form from another assembly you have to use the modifier attribute x:FieldModifier="public" or use the method proposed by Jean. 如果要从另一个程序集访问wpf表单上的控件,则必须使用修饰符属性x:FieldModifier =“public”或使用Jean提出的方法。

This may be a slightly different answer, but let's think about why we need to pass data between forms.这可能是一个稍微不同的答案,但让我们考虑一下为什么我们需要在表单之间传递数据。 obviously, the reason is 'visualization'.显然,原因是“可视化”。

use Delegate or Event.使用委托或事件。

There is no need to declare an element as Public just to make it visible.无需将元素声明为 Public 只是为了使其可见。 only need to be able to transform elements within a window using a delegate , on a limited basis.只需要能够在有限的基础上使用委托来转换窗口内的元素。

To access any control in another window is so simple. 访问另一个窗口中的任何控件非常简单。 Lets say to access from a Login window to MainWindow. 让我们说从登录窗口访问MainWindow。 Here is the steps: 以下是步骤:

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

Good programming 好编程

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM