jlu_weige 2018-01-11 02:05 采纳率: 100%
浏览 3772
已采纳

c#其他类调用主界面的textbox控件

先说明本人水平不高
做一个WPF软件,主界面中有一个TextBox,现在要在一个其他的类中向它中打印。
然后提示,调用线程必须为 STA,因为许多 UI 组件都需要。
现在想知道怎么能让MainWindow向这个类中传递此TextBox。
这个类是定时运行的,非主界面启动的,而且在主界面前加载。

  • 写回答

7条回答

  • hxycsdn9159 2018-01-11 09:25
    关注

    首先不建议楼主这样去进行传递,因为这样做的话会使你定义的类和MainWindow类产生紧耦合,这样的代码是最劣等代码,如果楼主只为了达成功能不在意这些的话方法还是有很多的,比如说你的这个类是class A{ },你在另外一个非UI线程创建了A的一个实例a,然后你想在这个线程内通过a的某个属性或者字段获取MainWindow实例里面一个Textbox输入框的引用,然后你这个类还是先于MainWindow类进行实例化的你可以这样:
    首先定义你的类A,有一个公共可访问的属性CurTextBox:
    public class A
    {
    public TextBox CurTextBox{ get; set;}
    。。。。。
    }
    然后这样在你的MainWindow类里面重载一个构造函数,并且为实例a的CurTextBox属性添加对当前Window上TextBox的引用:
    public class MainWindow
    {
    public MainWindow(A a)
    {
    if(a!== null)
    {
    a.CurTextBox = this.textbox1;

    }
    }
    }
    然后你要刷新这个TextBox的话需要这样:
    由于你是跨线程进行UI控件的调用,所以必须使用Dispatcher类的Invoke()或者BeginInvoke()方法:

    所以整体代码结构应该大概是这样:
    using System.Threading;
    namespace Test{
    class Program
    {
    A a = new A();//实例化A
    MainWindow win = new MainWindow(a);//实例化MainWindow

        //开启你的刷新线程
        Thread td = new Thread(()=>{
                //定时刷新
                While(true)
                {
                        .......
                        .......
                        Application.Current.Dispatcher.Invoke(new Action(()=>{
                                a.CurTextBox.Text = "abc";//进行刷新        
                        }));
                }
        });
        td.Start();
    

    }
    }
    这样的话就可以满足你的要求,但是这种方法真的太low,代码紧紧耦合到一起,以后需求一旦变更,你就等着哭吧,例如我把TextBox改成Label,你就需要改MainWindow构造函数的参数类型,还要改各个实例化赋值等,这样会累死你。所以有更好的方法去做这个事情,拿WPF来说,比较好的一个方法就是用资源Resource类,因为资源是全局可以访问的,不需要传递,代码大概是这样的:
    你只需要在MainWindow的构造函数内将资源赋值
    public class MainWindow
    {
    public MainWindow()
    {
    Application.Current.Resource["CurTextBox"] = this.textbox1;//这样就添加了一个全局可以访问的资源
    }
    }
    接下来是调用:

    using System.Threading;
    namespace Test{
    class Program
    {
    A a = new A();//实例化A(起始此时A根本就没必要了,如果你有其他需要处理的话保存)
    MainWindow win = new MainWindow();//实例化MainWindow

        //开启你的刷新线程
        Thread td = new Thread(()=>{
                //定时刷新
                While(true)
                {
                        .......
                        .......
                        Application.Current.Dispatcher.Invoke(new Action(()=>{
                                TextBox tb = Application.Current.Resource["CurTextBox"] as TextBox;
                                tb.Text = "abc";//进行刷新      
                        }));
                }
        });
        td.Start();
    

    }
    }
    这样不仅在这个线程内可以访问到textbox1,而且在整个Application的任何地方都可以随时访问这个textbox1。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(6条)

报告相同问题?

悬赏问题

  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
  • ¥30 用arduino开发esp32控制ps2手柄一直报错
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 求chat4.0解答一道线性规划题,用lingo编程运行,第一问要求写出数学模型和lingo语言编程模型,第二问第三问解答就行,我的ddl要到了谁来求了
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名
  • ¥65 汇编语言除法溢出问题
  • ¥15 Visual Studio问题