2013-04-09 29 views
0

让我们想象一下我有这个下面的类:输入的值映射到复杂的结构

[Serializable] 
public class Data{ 
    public string Prop1 { get; set;} 
    public int Prop2 { get; set; } 
} 

我建立一个自定义服务器控件,将它的值存储到input type=hidden领域,包含json这个类的序列化版本(在客户端使用某种javascript)。该值可能会被javascript代码修改,并且在客户端和服务器端都应该始终准确。

预期的HTML输出是,在首次启动:

<input type="hidden" value="{ Prop1:'zzz', Prop2: 42 }" /> 

为了让它简单易用的开发人员,我要发布这种类型的一个属性在我的服务器控件,可以直接写包括嵌套属性:

public class MyControl : WebControl { 

    public Data Data { 
     get; // correct implementation to be found 
    } 

} 

// somewhere else 

void foo(){ 
    var myControl = (MyControl)FindControl("my"); 
    myControl.Data.Prop1 = "some value"; 
    myControl.Data.Prop2 = 1234; 
} 

我应该如何写我的自定义控件的数据属性?

到现在为止,我写了这个代码:

public class MyControl : Control 
{ 
    protected HiddenField inputInternalValue; 

    protected override void CreateChildControls() 
    { 
     this.inputInternalValue = new HiddenField(); 
     this.Controls.Add(this.inputInternalValue); 
    } 

    private void inputInternalValue_ValueChanged(object sender, EventArgs e) 
    { 
     if (!string.IsNullOrEmpty(inputInternalValue.Value)) 
     { 
      // use of Newtonsoft's Json convert 
      m_Value = JsonConvert.DeserializeObject<MyControlValue>(inputInternalValue.Value); 
     } 
    } 

    protected override void OnPreRender(System.EventArgs e) 
    { 
     base.OnPreRender(e); 

     inputInternalValue.Value = JsonConvert.SerializeObject(Value); 

    } 

    [Serializable] 
    public class MyControlValue 
    { 
     public string Prop1 {get; set;} 
     public string Prop2 {get; set;} 
     public static MyControlValue Default() 
     { 
      return new MyControlValue 
      { 
       Prop1 = "some default value", 
       Prop2 = "999" 
      }; 
     } 
    } 

    private MyControlValue m_Value; 

    public MyControlValue Value 
    { 
     get 
     { 
      EnsureChildControls(); 
      if (m_Value == null) 
      { 
       if (!string.IsNullOrEmpty(inputInternalValue.Value)) 
       { 
        // use of Newtonsoft's Json convert 
        m_Value = JsonConvert.DeserializeObject<MyControlValue>(
         inputInternalValue.Value 
         ); 
       } 
       else 
       { 
        m_Value = MyControlValue.Default(); 
       } 
      } 
      return m_Value; 
     } 
    }   
} 

然而,这个代码工作,因为只有在第一次回传预期。如果我在页面上添加一个按钮,其中我尝试读取值,第一个回发值将保留,第二个则不会。

我认为我的问题与页面生命周期有关。我无法确定后期阅读已完成。

+0

我不知道这是relavent但是......在你的'OnPreRender'。 “价值”从哪里来? – 2013-04-09 13:52:24

+0

这是对控件的“Value”属性的调用。 – 2013-04-09 14:01:03

回答

0

Msdn's page: IPostBackDataHandler Interface的帮助下,我找到了一个可行的解决方案。

而不是将我的存储嵌套到<asp:hidden>控件,我手动编写回发处理。

下面是结果:

public class MyControl : Control 
{ 

    protected override void CreateChildControls() 
    { 
     // other controls 
    } 

    public MyControlValue Value 
    { 
     get 
     { 
      var obj = ViewState["Value"]; 
      return (MyControlValue)(obj != null ? obj : ViewState["Value"] = MyControlValue .Default()); 
     } 
     set 
     { 
      ViewState["Value"] = value; 
     } 
    } 

    public bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection) 
    { 
     var presentValue = JsonConvert.SerializeObject(Value); 
     var postedValue = postCollection[postDataKey]; 

     if (!string.IsNullOrEmpty(presentValue) && !presentValue.Equals(postedValue)) 
     { 
      Value = JsonConvert.DeserializeObject<MyControlValue>(postedValue); 
      return true; 
     } 
     else 
     { 
      return false; 
     } 
    } 

    public void RaisePostDataChangedEvent() 
    { 
     OnValueChanged(EventArgs.Empty); 
    } 


    #region Event 

    public event EventHandler ValueChanged; 

    protected virtual void OnValueChanged(EventArgs e) 
    { 
     if (ValueChanged != null) ValueChanged(this, e); 
    } 

    #endregion Event 

    [Serializable] 
    public class MyControlValue 
    { 
     public string Prop1 {get; set;} 
     public string Prop2 {get; set;} 
     public static MyControlValue Default() 
     { 
      return new MyControlValue 
      { 
       Prop1 = "some default value", 
       Prop2 = "999" 
      }; 
     } 
    } 
}