2

Container.RetrieveItems() は時間がかかるサービスを呼び出すので、非同期で呼び出したいと思います (アイテムが取得された後、Container クラスの List プロパティに設定されます)。アイテムの取得が完了したら、updatePanel 内にある gridView を更新したいと思います (updatePanel Mode="Conditional" および ScriptManager EnablePartialRendering="true"。UpdatePanel にはトリガー アイテムがありません)。

ブレークポイントを設定し、各ステップを実行しました。アイテムが取得され、グリッドがデータバインドされてから update が呼び出されます。例外はスローされていませんが、グリッドはコンテンツで更新されていません。トリガーと Timer.OnTick イベントを使用して UpdatePanel を更新するように設定すると、完全に機能しますが、アイテムが取得された後にのみ更新する必要があるため、サービス呼び出しの完了時に手動で UpdatePanel.Update() を起動するのが理想的です。

私はかなりの検索を行いましたが、すべての答えは「DataBind() を呼び出すのを忘れました」です。

不足しているものはありますか?

    private void UpdateGrid()
    {
        grid.DataSource = Container.List;
        grid.DataBind();
        updatePanel.Update();
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        var task = Task.Factory.StartNew(Container.RetrieveItems);
        task.ContinueWith((x) => UpdateGrid());
    }

更新: 問題を特定するために、より簡単なテストをセットアップしました。メソッドの完了時に Text プロパティが更新されるラベルを作成しました。ページが読み込まれるとメソッドが呼び出され、メソッドが終了すると updatePanel.Update() が呼び出されましたが、変更はありませんでした。

Jaimes のアドバイスに従って、Button_click のポストバック内で手動更新を呼び出してみたところ、実際にラベルが更新されました。そのため、非同期タスクの完了時にコンテンツを更新する最良の方法をまだ探していますが、現在のセットアップが機能していません。

4

2 に答える 2

2

ジェイミーは正しい軌道に乗っています。ページがレンダリングされた後、サーバーは新しいデータをクライアントに「プッシュ」できません。クライアントはリクエストを開始する必要があります。タイマーを設定するか、クライアントで JavaScriptsetTimeoutを使用して、サーバーを定期的にポーリングし、サーバーが完了したかどうかを確認します。

ウェブサービスアプローチ

もう 1 つの方法は、サーバー上に Web サービスをセットアップし、それをページから呼び出すことです。これは新しいスレッドで実行され、結果が利用可能になるとすぐにグリッドを非同期に更新します。

まず、WCF Web サービスをセットアップする必要があります。よくわからない場合は、これに関する何千もの記事があります。ここにそれらの 1 つがあります: http://www.codeproject.com/Articles/16973/Simple-Web-Service-using-WCF-Windows-Communication

これは、私のプロジェクトの 1 つからのサンプル コードです。

namespace UI.Web.WebServices
{
    [ServiceContract(Namespace = "WebServices")]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class WebServiceName
    {
        [OperationContract]
        [WebInvoke(ResponseFormat = WebMessageFormat.Json)]
        public FacilityResult[] MethodName()
        {
            FacilityService facilityService = new 
            return facilityService .GetAssignments()).ToArray();
        }
    }
}

 

クライアントから Web サービスを呼び出す

次に、JavaScript を使用して、ページからグリッドをデータバインドする必要があります: http://blog.ashmind.com/2007/06/21/client-side-databinding-with-aspnet-ajax-futures/

以下は、同じプロジェクトのサンプル コードです。このプロジェクトでは、リンクのサンプルのような純粋な JavaScript ではなく、jQuery を使用します。

<script type="text/javascript">
    function getGridData() {
        var payload = { }; // Put data to include here, if any

        $.ajax({
            type: "POST",
            url: "/WebServiceName.svc/MethodName",
            data: JSON.stringify(payload),
            contentType: "application/json",
            dataType: "json",
            success: function (msg) {
                bindResultsToGrid(msg.d);
            },
            error: function (xhr) { alert('error' + xhr.responseText); }
        });
    }

function bindResultsToGrid(data)
{
    ...
}
</script>

参考文献 http://aspalliance.com/1301_Unveil_the_Data_Binding_Architecture_inside_Microsoft_ASPNET_Ajax_10__Part_1

http://aspalliance.com/1301_Unveil_the_Data_Binding_Architecture_inside_Microsoft_ASPNET_Ajax_10__Part_2

于 2012-04-21T03:21:58.183 に答える
1

この問題に対する私の完全な解決策を共有したいと思いました。msigman の答えは大きな助けになりましたが、そこまでたどり着くことができませんでした。クライアント側から GridView にバインドするための実行可能な解決策が見つからなかったため、代わりに JavaScript からグリッドを作成しています。

1 - リクエストを処理するようにコントローラーをセットアップします

MVC コントローラーは、クライアント側から任意の .NET コードを呼び出すことができる AJAX を介してクライアント側から呼び出すことができます。これは重要な部分です。これは、コントローラー/サービスによってすべての機能と手間のかかる作業を行うことができるためです。ただし、JavaScript の柔軟性も引き続き利用できます。これを行う方法の完全な例をここに投稿しました。 JavaScript から ASP.NET 関数を呼び出しますか? . (Web フォームまたは MVC で使用できます)。

public class TimersController : ApiController
{
   public HttpResponseMessage<TimerDisplay[]> Get()
   {
       return new HttpResponseMessage<TimerDisplay[]>(
           TimerRepository.Get(), // all your .NET logic can be encapsulated here
           new MediaTypeHeaderValue("application/json")
        );
    }
}

2 - AJAX でリクエストを開始する

これは、ページのロード時に $(document).ready() イベントを処理するか、ボタンのクリックで、または定期的にタイマーで行うことができます。

        $.ajax({
            url: "api/timers",
            dataType: "json",
            success: function (result) { bindGrid(result); }
        })

3 - データをグリッドにバインドする

前述したように、クライアント側からデータを GridView にバインドする方法が見つかりませんでした。より良い解決策は、GridView を完全に削除することだと思います (これはサーバー側のコントロールであり、このタイプの状況には柔軟ではありません)。代わりに、Javascript からグリッドを生成できます。データを手動でループして自分で作成する<tr>こと<td>もできますが、これを実行できるグリッド/UI フレームワークがかなりあります。JSON データを直接バインドできる便利なグリッド オブジェクトを持つ UI フレームワークの 1 つは、Kendo UI ( http://demos.kendoui.c​​om /web/grid/index.html ) (他の多くの便利なウィジェットの中でも) です。この SO 投稿には、javascript UI フレームワークhttps://stackoverflow.com/questions/159025/jquery-grid-recommendationsに関するその他の提案が含まれています。

    function bindGrid(gridData) {
        var grid = $("#grid");
        grid.html("");
        grid.kendoGrid({
            columns: [
                { field: "Place", title: "Place" },
                { field: "Time", title: "Time" } 
            ],
            dataSource: {
                data: gridData
            },
            scrollable: false
        });
    }   
于 2012-06-19T07:26:23.280 に答える