Linqデータソース、GridViewソート
18770 ワード
最近Linqにハマって、ASPをやっています.NETのプロジェクトでは,元のDataTabのデータソースもLinq方式で取得したデータソース,すなわちIEnumerableの一例に置き換えた.GridViewにバインドすると、ソートの問題が発生します.大回りしてやっと分かった.NET 3.5で依頼した書き方で問題が解決しました.
まずGoogleでGridViewがIEnumerableデータソースのソートをどのように実現するかを見てみましょう.
明らかにこの案は、タイプソートの属性が多くなると死んだ人を書く.
それからまた《Gridview LINQとObjectDataSourceによる自動ページングとソート》のこの文章を参考にして、自分で文章を読むのは注意深くなくて、最初は分からなかったで、ブロガーは返事をしてからやっとSystemに追加することができることを知った.Linq.Dynamicの引用は、IQueryable.OrderBy(string sortExpression)関数.その後、生成、実行、放出異常、具体的な異常名が忘れられ、いずれにしてもクエリーを動的に作成できません.
この異常を投げ出したのは,前述の著者らが,IQueryableのTはLinq to Sqlが直接生成したモデルであり,私のプロジェクトでは,このモデルTはデータベースに直接対応するデータテーブルではないからである.私のデータベースにはTabがありますDeviceInfo(デバイス情報テーブル)とTab_DeviceStatus(デバイスステータステーブル)ですが、私のプログラムコードにはデバイスの情報とデバイスの状態を格納するDeviceクラスが1つしか定義されていません.
引き続き検索して、この文章を見て、本人の英語が比較的にこすっているため、実は多くの説明は理解していないで、コードの部分だけを見ました.著者らは、反射構造Expressionの例をパラメータとしてIQueryableを呼び出す.OrderBy(Expression sortExpression)関数はソートを実現します.よって、反射によりIEnumerableを構築することを考える.OrderBy(Funckey)のパラメータを呼び出します.
まず、Funcはdelegateです.『からNETフレームワークにおける依頼書き方の進化談を開く(中)』を参考にして分かりました.NET 3.5で依頼された書き方は、最後にソートに関する解決策を得ました.
変ですが、実現してみました.前にたくさん言ったが、実は私がこの問題を解決する過程にすぎない.ただし、Linq to Sqlとして自動的に生成される汎用型のソートを実現するために用いることができる.以下に完全な例コードを差し上げます.
デバイス類:
.aspxファイル:
.aspx.csファイル:
補足:
文章は昨日書いたもので、IEnumerablesource=data.Tab_DeviceInfos.Select(info => new Device(info));この行のコードには、昨日var source=_が使われていました.data.Tab_DeviceInfos.Select(info => new Device(info));.リリース後、ポイントダウンして運転して、異常を投げて、Systemに基づいてはいけません.Objectタイプを並べ替えます.IEnumberと直接宣言しないと、Select関数はIQueryableのインスタンスを返し、上記の異常が投げ出されます.解決策は、私のようにIEnumberableと宣言するか、sourceを先に呼び出すことができます.AsEnumerable()は、反射でそのタイプを取得し、強回転します.コードは次のとおりです.
ツールクラスcs:
.aspx.csでバインドされたデータ部分のコード:
まずGoogleでGridViewがIEnumerable
protected void GridView_Sorting(object sender, GridViewSortEventArgs e)
{
if (e.SortDirection == SortDirection.Ascending)
{
switch (e.SortExpression)
{
case "property1":
//IEnumber<T>.OrderBy(t => t.property1);
break;
case "property2":
//IEnumber<T>.OrderBy(t => t.property2);
break;
default:
break;
}
}
else
{
switch (e.SortExpression)
{
case "property1":
//IEnumber<T>.OrderByDescending(t => t.property1);
break;
case "property2":
//IEnumber<T>.OrderByDescending(t => t.property2);
break;
default:
break;
}
}
}
明らかにこの案は、タイプソートの属性が多くなると死んだ人を書く.
それからまた《Gridview LINQとObjectDataSourceによる自動ページングとソート》のこの文章を参考にして、自分で文章を読むのは注意深くなくて、最初は分からなかったで、ブロガーは返事をしてからやっとSystemに追加することができることを知った.Linq.Dynamicの引用は、IQueryable
この異常を投げ出したのは,前述の著者らが,IQueryable
引き続き検索して、この文章を見て、本人の英語が比較的にこすっているため、実は多くの説明は理解していないで、コードの部分だけを見ました.著者らは、反射構造Expressionの例をパラメータとしてIQueryable
まず、Funcはdelegateです.『からNETフレームワークにおける依頼書き方の進化談を開く(中)』を参考にして分かりました.NET 3.5で依頼された書き方は、最後にソートに関する解決策を得ました.
string sortExpression;
SortDirection sortDirection;
IEnumerable<Device> source;
//set value.
if (sortDirection == SortDirection.Ascending)
{
GridView1.DataSource = source.OrderBy(item => item.GetType().GetProperty(sortExpression).GetValue(item, null));
}
else
{
GridView1.DataSource = source.OrderByDescending(item => item.GetType().GetProperty(sortExpression).GetValue(item, null));
}
変ですが、実現してみました.前にたくさん言ったが、実は私がこの問題を解決する過程にすぎない.ただし、Linq to Sqlとして自動的に生成される汎用型のソートを実現するために用いることができる.以下に完全な例コードを差し上げます.
デバイス類:
public class Device
{
private Tab_DeviceInfo _deviceInfo;
/// <summary>
/// 。
/// </summary>
/// <param name="deviceInfo"></param>
internal Device(Tab_DeviceInfo deviceInfo)
{
_deviceInfo = deviceInfo;
// , 。
}
#region 。
/// <summary>
/// 。
/// </summary>
public int ID
{
get
{
return _deviceInfo.DI_ID;
}
set
{
_deviceInfo.DI_ID = value;
}
}
/// <summary>
/// 。
/// </summary>
public string NO
{
get
{
return _deviceInfo.DI_DeviceNO;
}
set
{
_deviceInfo.DI_DeviceNO = value;
}
}
#endregion
}
.aspxファイル:
<form id="form1" runat="server">
<div>
<asp:GridView ID="GridViewDevice" runat="server" AllowSorting="True" OnSorting="GridViewDevice_Sorting">
<Columns>
<asp:BoundField DataField="ID" HeaderText=" " SortExpression="ID" />
<asp:BoundField DataField="NO" HeaderText=" " SortExpression="NO" />
</Columns>
</asp:GridView>
</div>
</form>
.aspx.csファイル:
public partial class OrderByProperty : System.Web.UI.Page
{
private GSMDataContext _data;
/// <summary>
/// 。
/// </summary>
public OrderByProperty()
{
_data = new GSMDataContext();
}
private void bindGridViewData()
{
if (!IsPostBack)
{
GridViewDevice.DataKeyNames = new string[] { "ID" };
}
string sortExpression = GridViewDevice.Attributes["sortExpression"];
SortDirection sortDirection = GridViewDevice.Attributes["sortDirection"] == "ASC" ? SortDirection.Ascending : SortDirection.Descending;
IEnumerable<Device> source = _data.Tab_DeviceInfos.Select(info => new Device(info));
if (string.IsNullOrEmpty(sortExpression))
{
GridViewDevice.DataSource = source;
}
else
{
if (sortDirection == SortDirection.Ascending)
{
GridViewDevice.DataSource = source.OrderBy(item => item.GetType().GetProperty(sortExpression).GetValue(item, null));
}
else
{
GridViewDevice.DataSource = source.OrderByDescending(item => item.GetType().GetProperty(sortExpression).GetValue(item, null));
}
}
GridViewDevice.DataBind();
}
protected void Page_Load(object sender, EventArgs e)
{
bindGridViewData();
}
protected void GridViewDevice_Sorting(object sender, GridViewSortEventArgs e)
{
// sortExpression sortDirection。
string sortExpression = e.SortExpression;
string sortDirection = "ASC";
if (sortExpression.Equals(GridViewDevice.Attributes["sortExpression"]) && "ASC".Equals(GridViewDevice.Attributes["sortDirection"]))
{
sortDirection = "DESC";
}
GridViewDevice.Attributes.Add("sortExpression", sortExpression);
GridViewDevice.Attributes.Add("sortDirection", sortDirection);
bindGridViewData();
}
}
補足:
文章は昨日書いたもので、IEnumerable
ツールクラスcs:
public class SortUtility
{
public static object Sort(IEnumerable source, string sortExpression, SortDirection sortDirection)
{
IEnumerator sourceEnumerator = source.GetEnumerator();
if (!sourceEnumerator.MoveNext())
{
return null;
}
Type dataSourceType = source.GetType();
Type dataItemType = typeof(object);
if (dataSourceType.HasElementType)
{
dataItemType = dataSourceType.GetElementType();
}
else if (dataSourceType.IsGenericType)
{
dataItemType = dataSourceType.GetGenericArguments().FirstOrDefault();
}
else
{
if (sourceEnumerator.Current != null)
{
dataItemType = sourceEnumerator.Current.GetType();
}
}
// We'll handle things like LINQ to SQL differently by passing the love
// on to the provider.
PropertyInfo sortProperty = dataItemType.GetProperty(sortExpression);
// , 。
if (sortProperty == null)
{
return source;
}
Type sorterType = typeof(SortUtility<,>).MakeGenericType(dataItemType, sortProperty.PropertyType);
object sorterObject = Activator.CreateInstance(sorterType);
return sorterType.GetMethod("Sort", new Type[] { dataSourceType, typeof(string), typeof(SortDirection) })
.Invoke(sorterObject, new object[] { source, sortExpression, sortDirection });
}
}
public class SortUtility<T, ST>
{
public static IEnumerable<T> Sort(IEnumerable<T> source, string sortExpression, SortDirection sortDirection)
{
Func<T, ST> sortFunc = item => (ST)typeof(T).GetProperty(sortExpression).GetValue(item, null);
if (sortDirection == SortDirection.Ascending)
{
return source.OrderBy<T, ST>(sortFunc);
}
else
{
return source.OrderByDescending<T, ST>(sortFunc);
}
}
}
.aspx.csでバインドされたデータ部分のコード:
private void bindGridViewData()
{
if (!IsPostBack)
{
GridViewDevice.DataKeyNames = new string[] { "ID" };
}
string sortExpression = GridViewDevice.Attributes["sortExpression"];
SortDirection sortDirection = GridViewDevice.Attributes["sortDirection"] == "ASC" ? SortDirection.Ascending : SortDirection.Descending;
var source = _data.Tab_DeviceInfos.Select(info => new Device(info));
if (string.IsNullOrEmpty(sortExpression))
{
GridViewDevice.DataSource = source;
}
else
{
/*
if (sortDirection == SortDirection.Ascending)
{
GridViewDevice.DataSource = source.OrderBy(item => item.GetType().GetProperty(sortExpression).GetValue(item, null));
}
else
{
GridViewDevice.DataSource = source.OrderByDescending(item => item.GetType().GetProperty(sortExpression).GetValue(item, null));
}
*/
GridViewDevice.DataSource = SortUtility.Sort(source, sortExpression, sortDirection);
}
GridViewDevice.DataBind();
}