我不知道这篇文章还有什么标题,所以如果你有更好的标题,请随时编辑。
我有两个类:Form和Field。
Form有一个名为Fields的属性,它是一个Field对象列表。
表单有一个名为Prefix的属性。
Field有一个方法需要使用包含它的Form的Prefix属性。
以下是我现在正在做的事情:
class Form
{
private List<Field> fields;
public string Prefix { get; set; }
public void AddField(Field field)
{
field.Form = this;
fields.Add(field);
}
}
class Field
{
public void RenderHtml()
{
// render html element with ID attribute
// prefixed with the parent form's Prefix property
}
}
我该怎么做?
答案 0 :(得分:6)
我会这样做:
class Form
{
// ...
}
class Field
{
Form parent;
public Field(Form parent)
{
if (parent == null)
{
throw new ArgumentNullException("parent");
}
this.parent = parent;
}
// now you can reference this.parent to get at its owning form
// ...
}
答案 1 :(得分:3)
在上面调用Render时,将前缀传递给Field对象。依赖于字段知道其父窗体,以及具有前缀属性的窗体...您正在设置的依赖关系数量可能会变成维护噩梦。
如果你不能在Field.Render上传递前缀,请在Field上有一个property / set方法来传入新的前缀,并在Form上编写setter的自定义实现来设置所有的前缀在表单上设置时包含的字段。
您还可以使用事件做一些事情来获得类似的数据流。
答案 2 :(得分:0)
但说实话,我以前的答案很多:)
Form frm = new Form();
frm.AddField(new Field());
class Form
{
private List<Field> fields;
public string Prefix { get; set; }
public string formName;
public string prefix;
public void AddField(Field field)
{
field.RenderHTML(this.formName,this.prefix);
fields.Add(field);
}
}
class Field
{
public void RenderHTML(string prefix,string id)
{
// render html element with ID attribute
// prefixed with the parent form's Prefix property
}
}
OR ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Form frm = new Form();
frm.AddField(new Field(frm.formName,frm.prefix));
class Form
{
private List<Field> fields;
public string Prefix { get; set; }
public string formName;
public string prefix;
public void AddField(Field field)
{
field.RenderHTML(this.formName,this.prefix);
fields.Add(field);
}
}
class Field
{
public void Field(string prefix,string id)
{
// render html element with ID attribute
// prefixed with the parent form's Prefix property
}
}
答案 3 :(得分:0)
你也可以这样做......
public class Form
{
private Fields fields = new Fields(this);
public string Prefix { get; set; }
public void AddField(Field field)
{
field.Form = this;
fields.Add(field);
}
}
public class Fields: List<Field>
{
public Form Form { get; set; }
public Fields(Form form)
{ Form = form; }
public void Add(Field fleld)
{
field.Form = Form;
Add(field);
}
}
答案 4 :(得分:0)
你的方法绝对没有错。
也许我会考虑给Field
类提供Prefix
属性而不是this
引用,但这是一个细节...
答案 5 :(得分:0)
您可以从Collection派生FieldCollection类,并覆盖基类的InsertItem()方法以将父级连接到该字段。
public class Field
{
public string Prefix {get;set;}
}
public class FieldCollection : System.Collections.ObjectModel.Collection<Field>
{
private Form form;
public FieldCollection(Form f)
{
form = f;
}
protected override void InsertItem(int index, Field item)
{
base.InsertItem(index, item);
item.Prefix = form.Prefix;
}
}
public class Form
{
public string Prefix{get;set;}
public FieldCollection Fields = new FieldCollection();
}
答案 6 :(得分:0)
这是一种松散耦合的方式,这样Field就没有对Form的直接了解,而且表单通过使用Field上定义的事件来设置前缀
public class FieldEventArgs : EventArgs
{
public Field Field { get; private set; }
public FieldEventArgs(Field field)
{
Field = field;
}
}
public partial class Field
{
public event EventHandler<FieldEventArgs> OnBeforeRender;
public string Prefix { get; set; }
public void Render()
{
if (OnBeforeRender != null)
{
OnBeforeRender(this, new FieldEventArgs(this));
// render html or do whatever
}
}
}
public class Form
{
private List<Field> Fields;
public string Prefix { get; set; }
public void AddField(Field field)
{
field.OnBeforeRender += Field_OnBeforeRender;
Fields.Add(field);
}
void Field_OnBeforeRender(object sender, FieldEventArgs e)
{
e.Field.Prefix = Prefix;
}
}
答案 7 :(得分:0)
一般来说,子对象有四种方式可以获得父对象属性的值,按复杂程度递增的顺序排列:
在构造中设置子对象中的值。优点:所有出门都很简单。缺点:如果父属性发生变化,则子节点不同步;如果你有很多子对象,可以是内存耗尽,因为每个对象都有自己的值副本。
保持对父母的引用作为孩子的财产。优点:非常简单;当孩子要求时,属性值是最新的。缺点:如果您将孩子与其父母断开连接,或将其分配给新的孩子,则会出现问题;通常一个好主意是实现一个集合类,其Add
和Remove
方法管理父子关系;由于子对象保留对父对象的引用,因此在没有更多子对象之前不能处理父对象。
使用事件将属性更改的通知从父级分发给子级。优点:子对象不需要知道有关父进程实现细节的任何信息,或者即使 是父对象,也不需要知道任何内容,缺点:复杂;如果有很多子对象并且父属性经常变化,则表现不佳;初始化儿童财产可能不够优雅;如果子对象没有取消订阅,则不会被处置。
使用组合(例如数据绑定),以便第三类负责调解父和子之间的更新。优点:极其灵活;一旦你理解了组合基础设施,它就很容易使用 - 这就是为什么WPF有朝一日会征服地球的原因。缺点:具有方法#3的所有缺点,然后一些;如果你没有一个非常非常好的理由(一般来说,你没有),通常太复杂,不值得建立自己的基础设施;使用现有的基础设施(例如WinForms或WPF绑定对象)需要理解和实施相当数量的管道(例如INotifyPropertyChanged
或上帝帮助你,依赖属性)。