【问题标题】:Property is inaccessible due to its protection level财产由于其保护级别而无法访问
【发布时间】:2013-05-19 18:41:27
【问题描述】:

我需要发布到多行TextBox。数据来自单独类中的不同方法。

class converter
{
    public static void convert(object source, FileSystemEventArgs f)
    {
        //... some job done now post this data to winforms
        Form1.textBox1 = "File Copied" + "  " + 
                         DateTime.Now.ToString("HH:mm:ss tt") +
                         Environment.NewLine;
    }
}

我无法从此类访问textBox1。它说:

Form1.textBox1' 由于其保护级别而无法访问
非静态字段、方法或属性 Form1.textBox1' 需要对象引用

【问题讨论】:

  • 您确定您的文本框名为 textbox1 而不是 textBox1?知道您需要正确设置内容也可能很有用,例如:Form1.textBox1.Text = "MyText";
  • 是的,你是对的,我的错误。但现在的错误是:Form1.textBox1 is inaccessible due to it's protection level.
  • 不应该是Form1.textbox1.text而不仅仅是Form1.textbox1
  • @harhar:我试过它给了我上面编辑中的错误
  • @Adam K Dean - 我怀疑 OP 也在尝试跨线程更改它,这意味着如果不调用该方法将无法工作。

标签: c# .net winforms


【解决方案1】:

转到Form1 并在控件属性中将TextBox1 设为公共(按F4) 并将属性 modifiersFriend 更改为 Public

之后。您可以执行以下操作:

 Form1 form1 = new Form1;
 form1.TextBox1.Text = "File Copied" + "  " + DateTime.Now.ToString("HH:mm:ss tt") + Environment.NewLine;

【讨论】:

  • 如果表单已经实例化了怎么办?在这种情况下,此解决方案不起作用。
【解决方案2】:

您可以这样做的一种方法是在表单中添加一个字段:

public static TextBox textBox;

并将其设置为 form_load 中的文本框:

this.textBox = textBox1;

然后在上面的方法中,这样称呼它:

Form1.textBox.Text = ...

完整的工作示例:

using System;
using System.Windows.Forms;

namespace *Win
{
    public partial class Form1 : Form
    {
        public static TextBox textBox;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            textBox = textBox1;

            TestClass.StaticMethod();
        }
    }

    public static class TestClass
    {
        public static void StaticMethod()
        {
            Form1.textBox.Text = "works";
        }
    }
}

【讨论】:

    【解决方案3】:

    您确实应该使用表单的现有实例:

    var form = Form.ActiveForm as Form1;
    
    if (form != null)
    {
         form.textBox1.Text = "File Copied" + " " + DateTime.Now.ToString("HH:mm:ss tt") + Environment.NewLine";
    }
    

    你应该实际使用事件,这是更合适的设计,但上面应该可以工作。

    【讨论】:

    • textbox1 由于其保护级别而无法访问
    • @user726720 这是控件的默认属性,可以通过进入包含指定控件的窗体的设计视图,然后将控件的修饰符属性更改为公共或内部来解决。跨度>
    【解决方案4】:

    Form1 可能是表单类型的名称,而不是Form1 实例变量的名称。 由于convert 可能是从Form1 中的一个实例方法调用的,因此您可以移动

    给调用者而不是在转换中引入依赖

    convert.convert(...);
    textbox1 = "File Copied" + "  " + DateTime.Now.ToString("HH:mm:ss tt") +
               Environment.NewLine;
    

    【讨论】:

    • 我有开始/停止按钮。因此,如果我说使用我的方法启动控制转移到另一个类来完成某些工作,它永远不会真正转移回来,直到我说停止。所以现在按下开始并激活作业后,我希望将数据写入表单类中的多行文本框
    【解决方案5】:

    需要这样的东西:

    Form1.Invoke(new Action(delegate(){ textBox1.Text = "MyText"}));
    

    如果代码不正确,我们深表歉意,但它足以让您开始使用 google。

    如果上述方法不起作用,则可能:

    Form1.textBox1.Text.Invoke(new Action(delegate(){textBox1.Text="MyText"}));
    

    我不记得具体是怎么做的了。

    也许是这样的:

    Invoke(new Action(() =>
    {
        Form1.textBox1.Text = "MyString";
    }));
    

    【讨论】:

    • 表示非静态字段需要对象引用
    【解决方案6】:

    设置属性:Modifier = Public

    【讨论】:

    • 除非他有表单变量引用,否则这将不起作用。他只有类型Form1,没有form1。
    【解决方案7】:

    您可以将 TextBox 更改为 public,传递 Form1 的实例,但这些方法违反了封装的基本租户,类转换器不应该知道 Form1 及其控件的任何内容。

    更好的方法是让类转换器定义一个事件,如果调用者希望在转换器类完成其工作后收到通知并更新内部内容(文本框),则该类将调用该事件。

    class converter
    {
       public delegate void OnCopyComplete(string file);
       public event OnCopyComplete CopyComplete;
       public static void convert(object source, FileSystemEventArgs f)
       {
           //... some job done now NOTIFY the caller 
           if(CopyComplete != null) CopyComplete(source.ToString());
       }
    }
    

    在Form1实例中

    // tell to the converter class that this class wants to be notified when the work is finished
    converter.CopyComplete += new converter.OnCopyComplete(UpdateMyLabels);
    converter.convert(....);
    
    
    public void UpdateMyLabels(string file)
    {
        TextBox1.Text = "File Copied" + "  " + DateTime.Now.ToString("HH:mm:ss tt") + Environment.NewLine;
    }
    

    【讨论】:

    • +1 用于提及封装。类方法应该将结果返回给表单。
    【解决方案8】:

    为什么不将表单作为静态方法的参数包括:

    class converter
    {
     public static void convert(object source, FileSystemEventArgs f, Form frm)
    {
    //... some job done now post this data to winforms
    frm.textbox1 = "File Copied" + "  " + DateTime.Now.ToString("HH:mm:ss tt") + Environment.NewLine;
    }
    

    但请确保您的 Texbox 在您的 Form1 中是公开的

            public static TextBox textBox1;
    

    编辑

    因此,如果您不想要公共文本框,那么您必须在 Form1 中创建一个公共和静态属性,并在传递表单之前将文本框的值传递到那里:

     public static String fromTextBox { get; set; }
    

    然后在 Form1 中另外将文本框的值保存到 fromTextBox 属性:

     fromTextBox = textBox1.Text;
    

    所以,您现在可以像这样访问它:

     class converter
     {
      public static void convert(object source, FileSystemEventArgs f, Form frm)
      {
    //... some job done now post this data to winforms
     frm.fromTextBox = "File Copied" + "  " + DateTime.Now.ToString("HH:mm:ss tt") + Environment.NewLine;
     }
    

    【讨论】:

    • 这就是我不想在文本框上公开的重点,正如史蒂夫所说,这不是一个好主意
    • @user726720 您可能可以创建一个单独的公共和静态属性来存储文本框。请参阅上面的编辑。