我如何(通常)接受任何控件并设置它的Text属性(如果有)?

时间:2016-04-04 02:37:22

标签: c# winforms

作为进度条控件的一部分,我添加了一个方法来接受传递给它的任何控件,该控件将用作报告'的方法。进度或任务状态以及进度条本身上的显示:

public void SetReportObject( object obj ) {

}

我遇到的问题是,当我去设置Text值或某些控件有TextValue时,obj没有可用的属性,从而在IDE中生成错误,从而阻止了这一点编译。

我认为,应该实施某种typeof,但我不确定如何解决这个问题。传递的对象可以是任何用户控件。

我在WinForms项目中使用c#。

3 个答案:

答案 0 :(得分:2)

您可以使用反射来设置属性,而无需在编译时知道确切的类型。这样的事情会做:

public void SetReportObject( object obj )
{
    if(obj == null) throw new ArgumentNullException("obj");

    PropertyInfo textProperty = obj.GetType().GetProperty("Text");
    if(textProperty == null) throw new InvalidOperationException("The control must have a Text property");
    if(!textProperty.CanWrite) throw new InvalidOperationException("The control must have a setteable Text property");

    textProperty.SetValue(obj, "0%", null);
}

我认为您至少可以将Control作为基类参数而不是对象,但会根据您的使用情况而有所不同。我也怀疑这是不是一个好的做法,但肯定是这样做的。

答案 1 :(得分:2)

我不知道我是否理解你的问题。如果您正在处理某个不是Control的类型对象,我认为您的api需要消费者信息。

public void SetReportObject<T>(T obj, Expression<Func<T, string>> data)
    {
        string yourData = "Something to Notify";
        var exp = data.Body as MemberExpression;
        var pInfo = exp.Member as PropertyInfo;
        pInfo.SetValue(obj, yourData, null);
    }

按照您必须使用TextBox调用的示例:

SetReportObject<TextBox>(textBox1, x => x.Text);

答案 2 :(得分:1)

只需接受Control作为您的类型,就会有Text property所有控件都会实现。

public void SetReportObject( Control obj ) {
   obj.Text = "This is some text";
}

但是,如果您只是用它来报告进度,我建议抽象掉控制部分,而只是使用IProgress<int>

public void UpdateProgress(IProgress<int> progress) {
   progress.Report(_currentProgress);
}

在从非UI线程更新文本之前,这已经增加了不再需要control.Invoke的好处。