Winform自定义控件为什么“对象引用未设置为对象的实例”?

时间:2010-12-03 14:30:31

标签: c# winforms

我创建了一个具有最大值的自定义控件。添加if时(DesignMode)Parent.Refresh();它编译但在客户端它崩溃与消息错误:

  

对象引用未设置为对象的实例

调用堆栈:

at System.ComponentModel.ReflectPropertyDescriptor.SetValue(Object component, Object value)
at Microsoft.VisualStudio.Shell.Design.VsTargetFrameworkPropertyDescriptor.SetValue(Object component, Object value)
at System.ComponentModel.Design.Serialization.CodeDomSerializerBase.DeserializePropertyAssignStatement(IDesignerSerializationManager manager, CodeAssignStatement statement, CodePropertyReferenceExpression propertyReferenceEx, Boolean reportError)
at System.ComponentModel.Design.Serialization.CodeDomSerializerBase.DeserializeAssignStatement(IDesignerSerializationManager manager, CodeAssignStatement statement)
at System.ComponentModel.Design.Serialization.CodeDomSerializerBase.DeserializeStatement(IDesignerSerializationManager manager, CodeStatement statement) 

源代码:

[Category("Main")]
[Description("Max Value")]
[DefaultValue(100)]
public int Max
{
    get { return _max; }
    set { 
        _max = value;
        if (DesignMode)
        {
            Parent.Refresh();
        }
    }
}

4 个答案:

答案 0 :(得分:5)

试试这个:

if (DesignMode && Parent != null)
{
    Parent.Refresh();
}

当第一次设置值时,很可能控件尚未添加到其Parent中。

如果您查看表单的* .designer.cs,您会注意到在将添加到父表单之前,您的usercontrol的属性已分配。这就是你得到例外的原因。

答案 1 :(得分:2)

我有类似的问题。组件代码导致此错误。 在我的案例中,简单的解决方案是封装所有使用图形组件的代码:

if (this.Created)
{
  // insert code with other components here
}

不幸的是,此解决方案无法使用选项卡控件(当组件不在第一个可见选项卡上时)

在我的情况下,问题是由财产引起的。该属性具有子组件的主动初始化。最终的解决方案是:

[EditorBrowsable(EditorBrowsableState.Never)]
[Browsable(false)]
[Category("Main")]
[Description("...")]
[DefaultValue(MyDataClass.None)]
public MyDataClass Data
{
  get
  {
    return this.data;
  }
  set
  {
    if (object.ReferenceEquals(value, null))
      value = MyDataClass.None; // not null - valid state of no data
    if (this.Created)
    {
      this.textEdit.Text = value.ToString();
    }
    this.data = value;
  }
}

protected override void OnVisibleChanged(EventArgs e)
{
  base.OnVisibleChanged(e);
  if (!this.DesignMode)
    this.Data = this.data;
}

要消除错误,请使用[Browsable(false)]或覆盖OnVisibleChanged

答案 2 :(得分:0)

您还必须为Parent检查null,并确保您正在设置Parent对象,或者Parent.Refresh()将永远不会执行。

答案 3 :(得分:0)

我只运行代码并从适当的菜单中打开该表单。然后进行截屏并保存图像。然后转到解决方案资源管理器,打开“ .designer.cs”文件,复制代码并将其保存在记事本中。现在再次打开设计器,然后单击“忽略并继续”并确认。它为我工作。但是,如果缺少某些控件,则可以通过拖放创建该控件,然后查看保存的屏幕截图和“ .designer.cs”文件,以使该控件与以前一样。