【问题标题】:How can I access a control in WPF from another class or window如何从另一个类或窗口访问 WPF 中的控件
【发布时间】:2012-11-30 11:12:56
【问题描述】:

我想在 WPF 的 mainWindow 中访问我的控件,例如按钮或文本框,但我不能这样做。

在 Windows 窗体应用程序中非常简单,您可以将该控件的修饰符设置为 True,并且您可以从该 mainWindow 的实例访问该控件,但在 WPF 中我无法声明公共控件。我该怎么做?

【问题讨论】:

标签: c# wpf silverlight


【解决方案1】:

要访问另一个 WPF 表单中的控件,您必须将该控件声明为公共的。 WPF 中控件的默认声明是公共的,但您可以使用以下代码指定它:

<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)
  • 在新的类文件中,当我引用 System.Windows 然后使用这个 foreach 循环时,它会抛出空引用异常,因为没有窗口。
【解决方案2】:

不幸的是,WPF 的基础是数据绑定。以任何其他方式执行此操作都是“违背常规”,是一种不好的做法,而且编码和理解通常要复杂几个数量级。

对于您手头的问题,如果您有要在视图之间共享的数据(即使它只是一个视图),请创建一个包含表示数据的属性的视图模型类,并绑定到视图中的属性(s )。

在您的代码中,只管理您的视图模型类,不要接触实际视图及其视觉控件和视觉合成。

【讨论】:

    【解决方案3】:

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

    看起来很复杂,但它非常简单! 但是,可能不是最佳实践。

    假设我们在 MainWindow 中有一个 Label1 和一个 Button1,并且您有一个处理与称为 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
    【解决方案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;
    

    How can I access one window's control (richtextbox) from another window in wpf?

    【讨论】:

      【解决方案5】:

      当我开始 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
      

      您显然必须先实例化Whatever,然后才能在您的代码中调用ChangeObjProperties()

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

      【讨论】:

        【解决方案6】:

        只需像这样声明您的控件即可将其公开:

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

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

        【讨论】:

        • 只需将 x:Name 设置为所需控件即可开箱即用
        • ...如果您使用VB,请用大写P写“Public” :)
        • 默认是公开的。但问题不是你得到了回答。
        【解决方案7】:

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

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

        【讨论】:

          【解决方案8】:

          这可能是一个稍微不同的答案,但让我们想想为什么我们需要在表单之间传递数据。 显然,原因是“可视化”。

          使用委托或事件。

          没有必要为了让元素可见而将元素声明为 Public。 只需要能够在有限的基础上使用委托来转换窗口内的元素。

          【讨论】:

            【解决方案9】:

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

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

            良好的编程

            【讨论】:

            • 假设我们有两个表单,想要更改已经创建并打开的另一个表单的标签内容,而不是表单的新实例。
            • 请仔细阅读接受的答案。假设您有两个表单(form1 和 form2),在 form1 中有一个文本框并计算一些东西,现在您在 form2 中并且想知道运行时 form1.textbox 的值。如果你创建一个 form1 的新实例,它的文本框有默认值,但我们不想要默认值。
            • 对不起,伙计。谢谢
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2019-06-13
            • 1970-01-01
            • 1970-01-01
            • 2021-08-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多