結構前に発表されていて、なかなか試す機会がなかったInstantFeedback Modeを試してみました。
InstantFeedback UIについては、こちらを参照願います。
- Instant Feedback Mode
簡単に言うと、XtraGridなどでサーバーモードで読み込み時に、エンドユーザにローディング中なのが
分かるようにフィードバック用のUIを表示する機能です。
WinForms版(XtraGrid)だけでなく、WPF, Silverlight側(DXGrid)にも実装されています。
InstantFeedback Modeはサーバーモードで利用する事になります。
その際、特定のデータソースを設定する必要があります。
指定できるデータソースは以下の2つです。
- LinqInstantFeedbackSource
- XPInstantFeedbackSource
LinqInstantFeedbackSourceは、IQueryableを受け付けるデータソースです。
以下の場合などで使えます。
実際のデータソースは以下のようにしてイベントをハンドルして設定します。
lifLinqToSQL.KeyExpression = "OID"; lifLinqToSQL.GetQueryable += lifLinqToSQL_GetQueryable; lifLinqToSQL.DismissQueryable += lifLinqToSQL_DismissQueryable; void lifLinqToSQL_DismissQueryable(object sender, GetQueryableEventArgs e) { SampleLinqToSQL.DataClasses1DataContext context = e.Tag as SampleLinqToSQL.DataClasses1DataContext; context.Dispose(); } void lifLinqToSQL_GetQueryable(object sender, GetQueryableEventArgs e) { SampleLinqToSQL.DataClasses1DataContext context = new SampleLinqToSQL.DataClasses1DataContext(); e.QueryableSource = context.GetTable<SampleLinqToSQL.ServerSideGridTest>(); e.Tag = context; }
GetQueryableイベントにて、データソースを設定し、DismissQueryableイベントにて破棄します。
XPInstantFeedbackSourceは、XPO専門のデータソースです。
こちらも、イベントをハンドルして設定します。
xifDataSource.ObjectType = typeof(ServerModeGridProjects.ServerSideGridTest); xifDataSource.ResolveSession += xifDataSource_ResolveSession; xifDataSource.DismissSession += xifDataSource_DismissSession; void xifDataSource_ResolveSession(object sender, ResolveSessionEventArgs e) { Session session = new Session(); session.ConnectionString = _connectionString; session.Connect(); e.Session = session; } void xifDataSource_DismissSession(object sender, ResolveSessionEventArgs e) { IDisposable session = e.Session as IDisposable; if (session != null) { session.Dispose(); } }
ResolveSessionイベントにて、セッションを設定し、DismissSessionイベントにてセッションを破棄します。
以下サンプルです。
以下のサンプルでは、以下のデータソースを設定してInstantFeedback Modeを
試しています。
ついでに、サーバーモード無しで通常通りデータソースも設定しています。
利用しているデータベースは、DemoCenterに付属しているサーバーモード用テーブルを利用しています。
using System; using System.Collections.Generic; using System.Data; using System.Data.Common; using System.Data.SqlClient; using System.Linq; using System.Windows.Forms; using DevExpress.Data.Linq; using DevExpress.Xpo; using DevExpress.XtraGrid.Views.Grid; namespace WindowsFormsApplication1 { public partial class Form1 : Form { const string SQL_QUERY = @"SELECT * FROM ServerSideGridTest"; string _connectionString; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(); builder.DataSource = @".\SQLEXPRESS"; builder.InitialCatalog = @"ServerModeGridProjects"; builder.IntegratedSecurity = true; _connectionString = builder.ToString(); xifDataSource.ObjectType = typeof(ServerModeGridProjects.ServerSideGridTest); xifDataSource.ResolveSession += xifDataSource_ResolveSession; xifDataSource.DismissSession += xifDataSource_DismissSession; lifList.KeyExpression = "OID"; lifList.GetQueryable += lifList_GetQueryable; lifList.DismissQueryable += lifList_DismissQueryable; lifLinqToSQL.KeyExpression = "OID"; lifLinqToSQL.GetQueryable += lifLinqToSQL_GetQueryable; lifLinqToSQL.DismissQueryable += lifLinqToSQL_DismissQueryable; lifEntityFramework.KeyExpression = "OID"; lifEntityFramework.GetQueryable += lifEntityFramework_GetQueryable; lifEntityFramework.DismissQueryable += lifEntityFramework_DismissQueryable; (grdMain.MainView as GridView).ShowFindPanel(); } private void btnServerModeList_Click(object sender, EventArgs e) { grdMain.DataSource = null; grdMain.DataSource = lifList; } private void btnServerModeLinqToSQL_Click(object sender, EventArgs e) { grdMain.DataSource = null; grdMain.DataSource = lifLinqToSQL; } private void btnServerModeEntityFramework_Click(object sender, EventArgs e) { grdMain.DataSource = null; grdMain.DataSource = lifEntityFramework; } private void btnServerModeXPO_Click(object sender, EventArgs e) { grdMain.DataSource = null; grdMain.DataSource = xifDataSource; } private void btnNotServerModeList_Click(object sender, EventArgs e) { grdMain.DataSource = null; grdMain.DataSource = GetNormalModeDataSource(); } #region Entity Framework void lifEntityFramework_DismissQueryable(object sender, GetQueryableEventArgs e) { ServerModeGridProjectsEntities1 entities = e.Tag as ServerModeGridProjectsEntities1; entities.Dispose(); } void lifEntityFramework_GetQueryable(object sender, GetQueryableEventArgs e) { ServerModeGridProjectsEntities1 entities = new ServerModeGridProjectsEntities1(); e.QueryableSource = entities.ServerSideGridTest; e.Tag = entities; } #endregion #region Linq To SQL void lifLinqToSQL_DismissQueryable(object sender, GetQueryableEventArgs e) { SampleLinqToSQL.DataClasses1DataContext context = e.Tag as SampleLinqToSQL.DataClasses1DataContext; context.Dispose(); } void lifLinqToSQL_GetQueryable(object sender, GetQueryableEventArgs e) { SampleLinqToSQL.DataClasses1DataContext context = new SampleLinqToSQL.DataClasses1DataContext(); e.QueryableSource = context.GetTable<SampleLinqToSQL.ServerSideGridTest>(); e.Tag = context; } #endregion #region List<T> void lifList_DismissQueryable(object sender, GetQueryableEventArgs e) { // nop. } void lifList_GetQueryable(object sender, GetQueryableEventArgs e) { using (SqlConnection conn = new SqlConnection(_connectionString)) { conn.Open(); SqlCommand command = conn.CreateCommand(); command.CommandText = SQL_QUERY; SqlDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection); List<Model> models = new List<Model>(); foreach (DbDataRecord record in reader) { models.Add(new Model { OID = record.GetInt32(0), Subject = record.GetString(1), From = record.GetString(2) }); } e.QueryableSource = models.AsQueryable(); } } #endregion #region List<T> not ServerMode List<Model> GetNormalModeDataSource() { using (SqlConnection conn = new SqlConnection(_connectionString)) { conn.Open(); SqlCommand command = conn.CreateCommand(); command.CommandText = SQL_QUERY; List<Model> models = new List<Model>(); using (SqlDataReader reader = command.ExecuteReader()) { foreach (DbDataRecord record in reader) { models.Add(new Model { OID = record.GetInt32(0), Subject = record.GetString(1), From = record.GetString(2) }); } } return models; } } #endregion #region XPO void xifDataSource_ResolveSession(object sender, ResolveSessionEventArgs e) { Session session = new Session(); session.ConnectionString = _connectionString; session.Connect(); e.Session = session; } void xifDataSource_DismissSession(object sender, ResolveSessionEventArgs e) { IDisposable session = e.Session as IDisposable; if (session != null) { session.Dispose(); } } #endregion } class Model { public int OID { get; set; } public string Subject { get; set; } public string From { get; set; } } }
実行すると、以下の画面が表示されます。
どれかのボタンを押下すると、データソースが設定されます。
必要な分のデータソースを取得するまでの間、グリッドのシートコーナー(左上の隅)に
ローディングアニメーションが表示されます。(Instant Feedback UI)
ついでに、FindPanelを表示して検索できるかどうかも確認してみました。
で、ここでList
FindPanelで検索するとうまく検索できないことが分かりました。
設定方法がまずいのかなと思っていろいろ調整してみたのですが
何度やっても、うまくいかないのでDevExpressに報告したらバグ仕様との事です。
(追記:ドキュメント上に記載がないので、記載してくれるようDevExpress側に頼んだところ、次のバージョンのドキュメントで追記されるとのことです。)
そのうち修正されることを期待します。
(まあ、List
サンプルを以下の場所にアップしました。
試してみたい方はどうぞ。
2011/07/05 追記:
ドキュメントの「Find Panel」のページを見てみると、以下の注意事項が追記されていました。
(http://documentation.devexpress.com/#WindowsForms/CustomDocument8869)
Searches performed using a Find Panel are case insensitive.
Searches via the Find Panel for case-sensitive data sources in server mode are not supported. The Find Panel always converts a search string to lower-case before searching.
================================
過去の記事については、以下のページからご参照下さい。
いろいろ備忘録日記まとめ