ソート式バインディングの問題をどのように回避したかを次に示します。
SortExpression
実際のプロパティ名に設定する代わりに、列の序数の位置に設定します。
<Columns>
<asp:TemplateField HeaderText="Name" SortExpression="1" >
<ItemTemplate>
<%# Item.Name %>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Job Title" SortExpression="2" >
<ItemTemplate>
<%# Item.JobTitle %>
</ItemTemplate>
</asp:TemplateField>
</Columns>
次に、ハンドラーを gridview のSorting
イベントにアタッチします。
<asp:GridView runat="server"
OnSorting="Sorting"
...
イベント引数の 1 つは、前に定義した並べ替え式 ("1"
または"2"
) です。この値を使用して、並べ替え式を実際のプロパティ名にプログラムで再バインドできます。
注:このアプローチに従うことは、昇順/降順の自動切り替えをあきらめることを意味します。ただし、再実装することは特に難しくありません。
注: リフレクション ベースのアプローチを使用して、実行時にプロパティ名を決定しています。
protected void Sorting(object sender, GridViewSortEventArgs e)
{
int columnPosition;
if (!int.TryParse(e.SortExpression, out columnPosition))
{
return;
}
switch (columnPosition)
{
case 1:
e.SortExpression = Reflector.GetPropertyName<Employee>(o => o.Name);
break;
case 2:
e.SortExpression = Reflector.GetPropertyName<Employee>(o => o.JobTitle);
break;
}
var grid = (GridView)sender;
if (grid.SortExpression == e.SortExpression)
{
if (grid.SortDirection == SortDirection.Ascending)
{
e.SortDirection = SortDirection.Descending;
}
}
}
最後に、Reflector
上記の例で使用しているクラスのコードを次に示します。
/// <summary>Utility class. Provides static reflection-based utility methods.</summary>
public static class Reflector
{
#region Public Methods and Operators
/// <summary>Gets the name of the property that is accessed by the given expression. Usage: <c>Reflector.GetPropertyName<MyClass>(obj => obj.MyProperty);</c></summary>
/// <param name="selectorExpression">The expression that selects the property of which the name should be returned.</param>
/// <typeparam name="T">The type that defines the property.</typeparam>
/// <returns>The name of the property.</returns>
public static string GetPropertyName<T>(Expression<Func<T, object>> selectorExpression) where T : class
{
MemberExpression memberExpression;
var unaryExpression = selectorExpression.Body as UnaryExpression;
if (unaryExpression != null)
{
memberExpression = unaryExpression.Operand as MemberExpression;
}
else
{
memberExpression = selectorExpression.Body as MemberExpression;
}
if (memberExpression == null)
{
return null;
}
return memberExpression.Member.Name;
}
#endregion
}