从子窗体中更改父窗体的属性的正确方法是什么?

5

我想知道我是否正在正确地执行此操作。我有两个表单,一个父表单和一个子表单(选项对话框)。要从子表单更改父表单中的属性,我使用类似以下代码的代码:

// Create an array of all rich textboxes on the parent form.
var controls = this.Owner.Controls.OfType<RichTextBox>();

foreach (var item in controls) {
    if (chkDetectUrls.Checked)
        ((RichTextBox)item).DetectUrls = true;
    else
        ((RichTextBox)item).DetectUrls = false;
}

我在表单上只有一个RichTextBox。循环一个包含1个控件的数组似乎很荒谬。这是正确的方法吗,还是有更简单的方法?
1个回答

10

在父表单中修改属性是不合适的。相反,子表单应该触发一个事件,由父表单监听并相应地更改自己的值。

从子表单操作父表单会创建双向耦合 - 父表单拥有子表单,但子表单也对父表单具有亲密的了解和依赖关系。冒泡是此问题的解决方案,因为它允许信息向上(“冒泡”)流动,同时避免任何严格的耦合。

以下是事件的最基本示例。 它不包括传递事件中的特定信息(这可能是您需要的),但涵盖了概念。

在您的子表单中:

//the event
public event EventHandler SomethingHappened;

protected virtual void OnSomethingHappened(EventArgs e)
{
    //make sure we have someone subscribed to our event before we try to raise it
    if(this.SomethingHappened != null)
    {
        this.SomethingHappened(this, e);
    }
}

private void SomeMethod()
{
    //call our method when we want to raise the event
    OnSomethingHappened(EventArgs.Empty);
}

在您的父表单中:

void OnInit(EventArgs e)
{
    //attach a handler to the event
    myChildControl.SomethingHappened += new EventHandler(HandleSomethingHappened);
}

//gets called when the control raises its event
private void HandleSomethingHappened(object sender, EventArgs e)
{
    //set the properties here
}

如我上面所说,你可能需要在事件中传递一些特定的信息。我们可以用几种方法来实现这个目标,但最简单的方法是创建自己的EventArgs类和委托。看起来你需要指定某个值是true还是false,那么让我们使用它:

public class BooleanValueChangedEventArgs : EventArgs
{
    public bool NewValue;

    public BooleanValueChangedEventArgs(bool value)
        : base()
    {
        this.NewValue = value;
    }
}

public delegate void HandleBooleanValueChange(object sender, BooleanValueChangedEventArgs e);

我们可以更改事件以使用这些新签名:

public event HandleBooleanValueChange SomethingHappened;

然后我们传递我们的自定义 EventArgs 对象:

bool checked = //get value
OnSomethingHappened(new BooleanValueChangedEventArgs(checked));

然后我们相应地更改父级中的事件处理方式:

void OnInit(EventArgs e)
{
    //attach a handler to the event
    myChildControl.SomethingHappened += new HandleBooleanValueChange(HandleSomethingHappened);
}

//gets called when the control raises its event
private void HandleSomethingHappened(object sender, BooleanValueChangedEventArgs e)
{
    //set the properties here
    bool value = e.NewValue;
}

我是C#的新手,可以给一个简短的例子或链接吗?;-) - Bob Dylan
谢谢你的更新,它确实帮助我理解了你所说的内容。 - Bob Dylan
您也可以只使用 EventHandler<BooleanValueChangedEventArgs>,而无需创建自己的委托类型。这还将逻辑上标记为事件处理程序委托。 - Matthew Scharley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接