1

アイテムを表示、編集、および MSSQL データベースに挿入するために使用される FormView があります。FormView は LinqDataSource に接続されており、そのSelectingイベントを使用して、クエリ文字列で渡されたパラメーター (列) に基づいて FormView に表示されるデータをフィルター処理します。

FormView には、関連テーブルの値を表示する DropDownList があります。編集しようとする場合を除いて、すべてが正常に機能します-何らかの理由で、編集を保存しようとすると(値が選択されている場合でも)、DropDownList の選択された値は常に空になります。インサートは正常に機能します。

Selectingフィルタリングを行うイベントまで問題を追跡しました。フィルタリングを行うメソッドをコメントアウトすると、アイテムは正常に更新されますが、フィルタリングによって更新が中断される理由がわかりません。

これが私の(短縮された)FormViewです:

<asp:FormView ID="fvData" runat="server" AllowPaging="True" 
    DataKeyNames="ID" DataSourceID="ldsData" 
    ondatabound="fvData_DataBound">
    <EditItemTemplate>
        <table class="pad5">
            <tr>
                <td class="field-name">AREA:</td>
                <td><asp:DropDownList ID="cboAREA" runat="server" DataTextField="AREA_NAME" DataValueField="AREA1" SelectedValue='<%# Bind("AREA") %>' DataSourceID="ldsAreas" /></td>
            </tr>
            <tr>
                <td class="field-name">LOOP:</td>
                <td><asp:TextBox ID="txtLOOP" runat="server" Text='<%# Bind("LOOP") %>' /></td>
            </tr>
            <tr>
                <td class="field-name">LOOP DESCRIPTION:</td>
                <td><asp:TextBox ID="txtLOOP_DESCRIPTION" runat="server" 
            Text='<%# Bind("LOOP_DESCRIPTION") %>' style="width: 600px" /></td>
            </tr>
        </table>

        <asp:Button ID="btnUpdate" runat="server" Text="Update" CommandName="Update" CausesValidation="True" />
        <asp:Button ID="btnCancel" runat="server" Text="Cancel" CommandName="Cancel" CausesValidation="False" />
    </EditItemTemplate>
    <InsertItemTemplate>
        <table class="pad5">
            <tr>
                <td class="field-name">AREA:</td>
                <td>
                    <asp:DropDownList ID="cboAREA" runat="server" DataTextField="AREA_NAME" 
                        DataValueField="AREA1" SelectedValue='<%# Bind("AREA") %>' AppendDataBoundItems="true" DataSourceID="ldsAreas">
                            <asp:ListItem Text="" Value="" />
                        </asp:DropDownList>
                </td>
            </tr>
            <tr>
                <td class="field-name">LOOP:</td>
                <td><asp:TextBox ID="txtLOOP" runat="server" Text='<%# Bind("LOOP") %>' /></td>
            </tr>
            <tr>
                <td class="field-name">LOOP DESCRIPTION:</td>
                <td><asp:TextBox ID="txtLOOP_DESCRIPTION" runat="server" 
            Text='<%# Bind("LOOP_DESCRIPTION") %>' style="width: 600px" /></td>
            </tr>
        </table>

        <asp:Button ID="btnInsert" runat="server" Text="Insert" CommandName="Insert" CausesValidation="True" />
        <asp:Button ID="btnCancel" runat="server" Text="Cancel" CommandName="Cancel" CausesValidation="False" />
    </InsertItemTemplate>
</asp:FormView>

LinqDataSource:

<asp:LinqDataSource ID="ldsData" runat="server" 
    ContextTypeName="E_and_I.EAndIDataDataContext" EnableDelete="True" 
    EnableInsert="True" EnableUpdate="True" EntityTypeName="" 
    TableName="INSTRUMENT_LOOP_DESCRIPTIONs" onselecting="ldsData_Selecting" OrderBy="ID ASC" >
</asp:LinqDataSource>

私のldsData_Selecting方法:

protected void ldsData_Selecting(object sender, LinqDataSourceSelectEventArgs e)
{
    EI.FilterData<INSTRUMENT_LOOP_DESCRIPTION>(ref e, db.INSTRUMENT_LOOP_DESCRIPTIONs, this.db);
}

そして最後にEI.FilterData

public static void FilterData<T>(ref LinqDataSourceSelectEventArgs e, IEnumerable<T> source, EAndIDataDataContext db)
{
    if (HttpContext.Current.Request.QueryString.Keys.Count > 0)
    {
        var result = source.AsQueryable();
        bool filtered = false;

        // get column names
        var columnNames = db.Mapping.MappingSource.GetModel(typeof(EAndIDataDataContext)).GetMetaType(typeof(T)).DataMembers;

        foreach (string key in HttpContext.Current.Request.QueryString.Keys)
        {
            string val = HttpContext.Current.Request.QueryString[key];

            // check the query string key exists as a column in the table, etc
            if (columnNames.SingleOrDefault(c => c.Name == key) != null && val.Trim() != "" && val != "*")
            {
                result = result.WhereLike(key, val.Replace("?", "_").Replace("*", "%"));
                filtered = true;
            }
        }

        if (filtered)
            e.Result = result;
    }
}

結果をフィルタリングすると更新が中断される理由はありますか (そして、DropDownList のみ - テキストボックスは正常に動作します)? フィルタリングは完全に機能します (つまり、FormView は、ユーザーが入力したレコード ベースのパラメーターのみを表示します)。WhereLike拡張メソッドが何をするのか疑問に思っている場合は、この質問の回答を確認してください。

4

2 に答える 2

0

2 つのケースのドロップダウン リストに違いがあり、おそらくこれが原因だと思います。Insert の場合、AppendDataBoundItems="true" がありますが、その上の Update フォームの場合、このフラグは設定されていません (デフォルトは false です)。送信フォームに関してこれが意味することは、挿入フォームの場合、再バインド時に項目をクリアするのではなく、現在のリストに追加することです。ただし、更新フォームの場合、追加するように設定されていないため、アイテムがクリアされ、バインドされます。したがって、バインディングは両方のケースで発生しますが、更新フォームの場合、それが発生したときにアイテムがクリアされ、空のデータを提供します。

最終的にフォームが失敗する原因となるポストバックでのフィルタリングを拒否する代わりに、ポストバックを引き起こしたコントロールに基づいてフィルタリングします。関数の上部で、ポストバックの原因となったコントロール ID をキャプチャできます。次に、データ ストレージ ステップをトリガーしているボタンからのポストバックではない場合にのみフィルタリングできます。それが整っていれば、AppendDataBoundItems フラグを完全に廃止できるはずです。

私が意味することのコードスニペットの更新:

string initControl = Request.Form["__EVENTTARGET"];
if (!IsPostBack || (initControl != "btnInsert" && initControl != "btnUpdate") {
    // code here
}

これが行うことは、PostBack のチェックを拡張して、(以前にテストした) ポストバックでない場合でも条件が許可されるようにすることですが、重要なことに、フォームがポストバックされている場合に限り、リストを更新することもできます。ポストバックするコントロールは、それらのバインドされた要素の内容に依存するイベントをトリガーするものではありません。これは、最初のページの読み込みでのみ機能するという問題を回避することを意味するはずです.

さらに、コントロールをバインドする必要がある場合は、スクリプトにグローバルなブール変数を追加できます。デフォルトでは False に設定し、上記の条件が満たされない場合 (つまり、バインディングを防止している場合) は True に設定します。次に、Page_PreRender 関数でそのブール値を確認できます。true に設定されている場合は、そのステップでコントロールの遅延バインドを実行できます (これは、Insert/Update イベントが既に処理された後にのみ発生するため、その時点はフォーム処理の結果に影響しなくなります)。

于 2012-08-31T21:40:36.100 に答える
0

編集してデータを投稿すると、データが再バインドされ、選択した値が消去されるためです。

解決策:バインドを調整する

If( !  IsPostBack)
{
  //Here realize your bind of data

}

データを永続化するには、ViewState を使用します

このソリューションでは、投稿時にデータを再バインドしないため、ViewState には選択した値が含まれます

于 2012-08-30T16:31:45.077 に答える