2010-11-27 13 views
6

私はページ上にグリッドを持つウェブサイトを設計しています。グリッドには複数のコンボボックスがあります。これらのコンボボックスは相互作用します。つまり、ある値がユーザーによって変更されたときに、別の値が値変更または無効/有効にされているとき。FindControlをたくさん使用する必要があることがわかりました。あるコンボボックスのselectedindexchangedイベントのように、別のコンボボックスを見つける必要があります。グリッド内の対話型コントロール

これはむしろ面倒なやり方です。また、コンボボックスにIDが後で変更された場合、コンパイラが見つけられないエラーをシステムに残すように見えます。

誰かがこれについてもっと良い方法があると教えてもらえますか?

答えて

0

私はASP.NETからSilverlightで開発し、そのMVVMパターンを活用しています。 ASP.NETのGridViewアイテムテンプレートを使用しても、各アイテムを直接バインドしたり、認識したり、同じテンプレート内の別のアイテムを参照することはできません。コードビハインドは、ある程度(通常は最大)、ビューコントロールのコンポジション階層を知る必要があります。

「より良い拘束力のある世界」に近づくためにできることは次のとおりです。コンボボックスは同じリストデータソースにバインドしますが、アイテム/コントロールの各行が作成されると、各アイテムをオブジェクト(つまりタグアイテム)に関連付けます。次に、コントロールのイベント処理では、イベントを発生させたコントロールに関連付けられたタグ項目に関連付けられている他のコントロールを取得し、それらのコントロールを実行します。

私は知っている、最高のアイデアではなく、ちょうど私の頭の上から。たぶん私はこれについてもっと考える時間があったときに私はこの投稿を更新することができます。

1

私はあなたのことを達成するために、さまざまなFindControlの並べ替えを広範囲に利用するウェブアプリを持っています。それは脆い(テストせずにコントロールIDを変更しないでください)、いくつかのユーティリティー機能によってわずかに煩わしくなることはありません。ここで私が使用するすべてのFindControlタイプの関数があります - これは少なくともあなたを助けるかもしれません。

/// <summary> 
/// Recursively searches for a control within the heirarchy of a given control. 
/// </summary> 
/// <param name="root">The control to search within.</param> 
/// <param name="id">The ID of the control to find.</param> 
/// <returns>The Control object of the found control, or null if the control isn't found.</returns> 
public static Control FindControlRecursive(Control root, string id) 
{ 
    if (root.ID == id) return root; 

    foreach (Control c in root.Controls) 
    { 
     Control t = FindControlRecursive(c, id); 
     if (t != null) return t; 
    } 

    return null; 
} 

/// <summary> 
/// Recursively searches for a control within the heirarchy of a given control using the Client ID 
/// of the control. Calling this too early in the lifecycle may not behave as expected. 
/// </summary> 
/// <param name="root">The control to search within.</param> 
/// <param name="clientID">The Client ID of the control to find.</param> 
/// <returns>The Control object of the found control, or null if the control isn't found.</returns> 
public static Control FindControlRecursiveByClientID(Control root, string clientID) 
{ 
if (0 == String.Compare(root.ClientID, clientID, true)) return root; 

foreach (Control c in root.Controls) 
{ 
    Control t = FindControlRecursiveByClientID(c, clientID); 
    if (t != null) return t; 
} 

return null; 
} 

/// <summary> 
/// Recursively searches for a group of controls within the heirarchy of a given control tree using the ID 
/// of the control. 
/// </summary> 
/// <param name="root">The control tree to search within.</param> 
/// <param name="id">The ID of the control to find.</param> 
/// <returns> 
/// A collection of the found controls. The collection will be empty if none are found. 
/// </returns> 
public static List<Control> FindControlsRecursive(Control root, string id) 
{ 
List<Control> collection = new List<Control>(); 
FindControlRecursive(root, id, collection); 
return collection; 
} 

private static void FindControlRecursive(Control root, string id, List<Control> collection) 
{ 
foreach (Control c in root.Controls) 
{ 
    if (0 == String.Compare(c.ID, id, true)) collection.Add(c); 
    else FindControlRecursive(c, id, collection); 
} 
} 

/// <summary> 
/// Recursively searches for a control within the heirarchy of a given control using the type 
/// of the control. 
/// </summary> 
/// <typeparam name="T">The type of the control to find.</typeparam> 
/// <param name="root">The control to search within.</param> 
/// <returns> 
/// The Control object of the found control, or null if the control isn't found. 
/// </returns> 
public static T FindControlRecursiveByType<T>(Control root) 
where T : Control 
{ 
if (root is T) return (T)root; 
foreach (Control c in root.Controls) 
{ 
    Control t = FindControlRecursiveByType<T>(c); 
    if (t != null) return (T)t; 
} 
return null; 
} 

/// <summary> 
/// Recursively searches for a set of controls within the heirarchy of a given control using the type 
/// of the control. 
/// </summary> 
/// <typeparam name="T">The type of the control to find.</typeparam> 
/// <param name="root">The control to search within.</param> 
/// <returns> 
/// A generic List object containing the controls found, or an empty List of none were found. 
/// </returns> 
public static List<T> FindControlsRecursiveByType<T>(Control root) 
where T : Control 
{ 
List<T> collection = new List<T>(); 
FindControlRecursiveByType<T>(root, collection); 
return collection; 
} 

private static void FindControlRecursiveByType<T>(Control root, List<T> collection) 
where T : Control 
{ 
foreach (Control c in root.Controls) 
{ 
    if (c is T) collection.Add((T)c); 
    else FindControlRecursiveByType<T>(c, collection); 
} 
} 
0

イベントを使用して通知を行うのはどうですか?

0

これは非常に乱雑です。

ここは非常にシンプルで洗練されたソリューションです。グリッドが3列の表にデータを表示する必要があるとします。データは以下の構造を持つオブジェクトから来ている:

マークアップ(GridDisplayRow.ascx):

[Serializable] 
public class Foo 
{ 
    public string Bar1 { get; set; } 
    public string Bar2 { get; set; } 
    public string Bar3 { get; set; } 
} 

は、その後、あなたのユーザーコントロールは、次のマークアップを持っています

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="GridDisplayRow.ascx.cs" Inherits="GridDisplayRow" %> 
<div> 
    <div class="cell"> 
     <asp:TextBox id="TxtProperty1" runat="server"/> 
    </div> 
    <div class="cell"> 
     <asp:DropDownList ID="DDLProperty2" runat="server" OnSelectedIndexChanged="DDLProperty2_OnSelectedIndexChanged" AutoPostBack="true"> 
     </asp:DropDownList> 
    </div> 
    <div class="cell"> 
     <input type="radio" id="RadProperty3" runat="server"> 
    </div> 
</div> 

お知らせすべてdivタグ。子供たちのdivは浮かんでいるので、並べて表示されます。

分離コード(GridDisplayRow.ascx.cs):

class GridDisplayRow:UserControl 
{ 
    public event EventHandler<System.EventArgs> SomethingHappened; 

    protected void Page_Load(object sender, EventArgs e) 
    { 
     //Initialize the drop down with something; 
    } 

    //this is where we handle internal events generated by children controls. 
    //Eg: the drop down's index changed. 
    protected void DDLProperty2_OnSelectedIndexChanged(object sender, EventArgs e) 
    { 
     //we update some other child control in this... 
     this.TxtProperty1.Text = this.DDLProperty2.Value; 

     //and maybe we want to signal the page that some event happened 
     if(SomethingHappened != null) 
     { 
      //Notify the page that SomethingHappened event occured 
      SomethingHappened(this, EventArgs.Empty); 
     } 
    } 

    //This is where the binding happens 
    public object BindingObject 
    { 
     set 
     { 
      Foo temp = (Foo)value; 
      this.TxtProperty1.Text = temp.Bar1; 
      this.DDLProperty2.Value = temp.Bar2; 
      this.RadProperty3.Value = temp.Bar3; 

      this.ViewState["Foo"] = temp; 
     } 
    } 
} 

だから我々は、fooへの結合を処理している上記のコードでは、他の言葉で我々がコントロールの(DIV)、各セル内のFooのプロパティを表示しています。上記のプロパティがオブジェクト型で、Grid/Repeater/WhatのItemTemplateにGridDisplayRowのインスタンスをContainer.DataItemオブジェクトにバインドするため、以下のようにキャストが必要です。

ページマークアップ:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Test.aspx.cs" Inherits="Test" %> 
<%@ Register src="GridDisplayRow.ascx" tagname="GridRow" tagprefix="ctrl" %> 

<asp:GridView ID="GridView1" runat="server"> 
    <Columns> 
     <asp:TemplateField> 
      <HeaderTemplate> 
       <div> 
        <div class="header cell">Header 1</div> 
        <div class="header cell">Header 2</div> 
        <div class="header cell">Header 3</div> 
       </div> 
      </HeaderTemplate> 
      <ItemTemplate> 
       <ctrl:GridRow ID="Row" runat="server" BindingObject='<%# Container.DataItem %>' OnSomethingHappened="Row_SomethingHappened" /> 
      </ItemTemplate> 
     </asp:TemplateField> 
    </Columns> 
</asp:GridView> 

を私が働いて好きではないだけで、あなたのデータソースは、例えばデータセットであれば、あなたがたDataRowにキャストする必要がある、または任意の適切なデータ型が必要であることに注意してくださいそれらは面倒で扱いにくいので、グリッドを使用してください。この例では、グリッドをトリックして1行に1つのセルを持つテーブルを作成し、そのセル内のレイアウトをスタイルシートで処理しました。

これは超効率的でオーバーヘッドが少ないため、リピータの方が効果的です。

グリッドをバインドする: IEnumerableを実装するすべてのソースを使用して、グリッドにバインドできます。 Listなどのコレクションで十分です。

GridRowコントロールがイベントを発生させると、コントロール自体への参照がオブジェクト送信者経由で送信されるため、送信者を正しいタイプにキャストすると、コントロールの内部プロパティを取得することができます。

このような方法の利点は、抽象化です。各コントロールは、独自のイベントを処理することができますか、または内部で発生したイベントのページに通知することを選択しました.... bla bla bla。あなたはその考えを得る。

0

ListViewを使用してみると、そのような要件をより簡単に管理できます。あなたがUpdate Panelの中にListViewを置くと、より良いユーザーエクスペリエンスを得ることができます