2013-04-09 28 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" 
      }; 
     } 
    } 
}