How to access WPF MainWindow Controls from my own

2020-05-17 06:57发布

I am a NOVICE and am very much struggling with what seems should be a very simple task. How do I modify a property of a MainWindow TextBlock, from another cs file. An exact code solution would be extremely helpful.

Below is the stripped down code. Is my use of static class causing me extra issues?

In File: MainWindow.xaml

<Window x:Class="TestApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TextBlock x:Name="TextBlock1" HorizontalAlignment="Left" Margin="107,71,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top"/>
    </Grid>
</Window>

In File: MainWindow.xaml.cs

namespace TestApp1  
{  
public partial class MainWindow : Window  
    {  
        public MainWindow()  
        {  
            InitializeComponent();  
            TextBlock1.Text = "Setting Text from MainWindow";  
            MyProgram.myProgramStart();  
        }  
    }  
}  

In File: CodeFile1.cs

namespace TestApp1
{
    public static class MyProgram
    {
        public static void myProgramStart()
        {
            // ... blah blah blah

            // I want to do something like follows, but won't compile
            MainWindow.TextBlock1.Text = "Setting Text from My Program";
        }
    }
}  

标签: c# wpf controls
7条回答
祖国的老花朵
2楼-- · 2020-05-17 07:26

You can simply achieve this using MVVM. You shouldn't directly access controls in View using its name from another class. You have to use binding properties.

First of all add a class, this will be your ViewModel Add your properties to this class which will be binded to your input controls in your View.

Student ViewModel

public class Student
{
    public string Name
    {
        get { return "Setting Text from My Program"; }
    }
}

App.Config

Now you have add to this View Model as a resource in your App.Config file. First add the name space reference to your app.config where your VM resides. [xmlns:local="clr-namespace:WpfApplication2]. Add your VM class as a resource by specifying your View Model class name(student).

<Application x:Class="WpfApplication2.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml"
             xmlns:local="clr-namespace:WpfApplication2">

    <Application.Resources>
        <local:Student x:Key="Student" />
    </Application.Resources>
</Application>

MainWindow.xaml

Set the DataContext with the resource key added to App.config and Set the binding to the property defined in the Student View Model.

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        DataContext="{StaticResource Student}"
        Title="MainWindow" Height="350" Width="525">

    <Grid>
        <TextBlock Text="{Binding Name}" Height="23" HorizontalAlignment="Left" Margin="127,124,0,0" Name="textBlock1" VerticalAlignment="Top" Width="214" />
    </Grid>
</Window>
查看更多
再贱就再见
3楼-- · 2020-05-17 07:38

Use MVVM pattern to access properties of the control and modify them:

public class Student
{
    public Student()
    {
    }

    public string Name
    {
        get { return "Setting Text from My Program"; }
    }
}

Set the DataContext of the XAML in the code behind:

this.DataContext = new Student();

Bind the Text property to Name:

<TextBlock Text="{Binding Name}"/>
查看更多
倾城 Initia
4楼-- · 2020-05-17 07:38

You need to create an instance of MainWindow.

But there shouldn't be a reason to do that because it will be done automagically in an WPF app. Unless you have specific reason to do that (which I doubt because of this question and because you say you're a novice).

查看更多
地球回转人心会变
5楼-- · 2020-05-17 07:44

As for why it won't compile, I will assume the compiler error you are getting is...

An object reference is required for the non-static field, method, or property 'TestApp1.MainWindow.TextBlock1'

This happens because you are trying to access an TextBlock1 as if it were static. As @JeffRSon stated, create an instance of your MainWindow class first.

// Create an instance of MainWindow
var mainWindow = new MainWindow();
mainWindow.TextBlock1.Text = "Setting Text from My Program";

I assume you may want to display the window as well...

mainWindow.ShowDialog();
查看更多
戒情不戒烟
6楼-- · 2020-05-17 07:44

To extend on what Nathan said, I used a safe cast:

(System.Windows.Application.Current.MainWindow as MainWindow)?.TextBlock1.Text = "Setting Text from My Program";

Note the comments on the answer Nathan gave. This isn't ideal but it works.

查看更多
Explosion°爆炸
7楼-- · 2020-05-17 07:47

Basically there are more than 2-3 methods. Given method is quite easier to understand & handle. You can access MainWindow controls by following codes (1),(2),(3),(4).

In File: MainWindow.xaml.cs

  public partial class MainWindow
  {
   internal static MainWindow Main; //(1) Declare object as static
   public MainWindow()
    {
        InitializeComponent();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
       Main =this; //(2) Defined Main (IMP)
      var AnyClassORWindow=new Class1(); //Initialize another Class
      AnyClassORWindow.ShowValue();
    }
  }

In File: Class1.cs

  internal class Class1 : MainWindow //(3) Inherited
    {
      internal void Display()
        {
           MessageBox.Show(Main.TextBox1.Text); //(4) Access MainWindow Controls by adding 'Main' before it.
         }
     }

Notes:-

  1. It's good practice to use code (2) after window LOADED not in CONSTRUCTOR.
  2. Code (2) in constructor may leave run-time problems.
  3. Another simple method is to use 'ref MainWindow_field' by passing to each class's Constructor OR assign '(MainWindow) Application.Current.MainWindow' to static Main.
查看更多
登录 后发表回答