jqGrid选择列表的自定义Linq扩展方法

时间:2011-03-28 14:51:47

标签: c# .net linq jqgrid

我有一个自定义方法,用于获取与jqGrid一起用于搜索的选择列表的字符串。

所需的字符串格式为":All;value1:text1;value2:text2"我目前有以下方法以可重用的方式实现此目的:

public static string jqGridFilterSelectList<TSource>(this IQueryable<TSource> source,Expression<Func<TSource, string>> selector)
{
     return string.Join(";", source.Select(selector).Distinct().ToArray()); 
}

这可行,但需要调用如下:

string filterSelectList = service.GetAllUsers().jqGridFilterSelectList(x=>x.User + ":" + x.User);

我不太乐意使用像x=>x.User + ":" + x.User这样的选择器。我想把它转换成2个这样的重载(伪代码!!)

// case where we want the value and text of the select list to be the same
public static string jqGridFilterSelectList<TSource>(this IQueryable<TSource> source,Expression<Func<TSource, string>> selector)
{
     return string.Join(";", source.Select(selector + ":" + selector).Distinct().ToArray()); 
     //obviously this won't work, but is it possible in some other way while executing it on the database still? Also is it possible to insist the selector only contains 1 column.
}

//case where we want different text and value
public static string jqGridFilterSelectList<TSource>(this IQueryable<TSource> source,Expression<Func<TSource, string>> textSelector,Expression<Func<TSource, string>> valueSelector)
{
     return string.Join(";", source.Select(valueSelector + ":" + textSelector).Distinct().ToArray()); 
}

我想我可以使用动态linq实现这一点,但我很想知道这是否可行。

2 个答案:

答案 0 :(得分:1)

如果我理解正确,你几乎已经写好了:

public static string jqGridFilterSelectList<TSource>(
    this IQueryable<TSource> source, 
    Expression<Func<TSource, string>> selector
)
{
     var compiled = selector.Compile();
     return string.Join(";", 
         source.Select(x => compiled(x) + ":" + compiled(x))
             .Distinct().ToArray()
     ); 
}

//case where we want different text and value
public static string jqGridFilterSelectList<TSource>(
    this IQueryable<TSource> source, 
    Expression<Func<TSource, string>> textSelector, 
    Expression<Func<TSource, string>> valueSelector
)
{
     return string.Join(";", 
         source.Select(x => valueSelector.Compile()(x) + ":" + textSelector.Compile()(x))
             .Distinct().ToArray()
     ); 
}

只需要调用你的选择器函数来获取值。 如果我误解了你的问题,请告诉我。

对于第二个问题,是否可以坚持选择器只包含1列,简单答案是否 - 选择器几乎可以是任何有效Func的{​​{1}并且返回TSource并且没有办法限制内部可以做的事情(除非你想检查提供的表达式树,但它会比结果更复杂,当然)。

编辑:好的,这是某种SQL LINQ提供程序,实体框架?所以让我们尝试一下不同的方式。我不知道它是否可行,但让我们先尝试获取数据并连接对象:

string

其他 public static string jqGridFilterSelectList<TSource>( this IQueryable<TSource> source, Expression<Func<TSource, string>> selector ) { var compiled = selector.Compile(); return string.Join(";", source.Distinct().AsEnumerable() .Select(x => compiled(x) + ":" + compiled(x)) .ToArray() ); } //case where we want different text and value public static string jqGridFilterSelectList<TSource>( this IQueryable<TSource> source, Expression<Func<TSource, string>> textSelector, Expression<Func<TSource, string>> valueSelector ) { return string.Join(";", source.Distinct().AsEnumerable() .Select(x => valueSelector.Compile()(x) + ":" + textSelector.Compile()(x)) .ToArray() ); } 调用在数据库和进程内处理之间切换。假设您的选择器是确定性的并且没有任何副作用,您可以对已经提取的ToEnumerable项进行操作。

答案 1 :(得分:1)

实现所需内容的另一种方法是使用searchoptionsdataUrlbuildSelect参数。

如果value字符串形式为&#34;:All; value1:text1; value2:text2&#34;在真正需要之前不会建造(直到第一次搜索)。当用户单击搜索对话框时,jqGrid将从dataUrl获取数据。服务器方法可以具有非常清晰的接口并返回List<string>的JSON表示。在客户端,您可以定义buildSelect事件句柄,将["text1", "text2", ...]转换为<select>。一切都好。使用这种方法的示例可以找到here。与示例相比,您只需在select元素中添加其他选项<option value="">All</option>

有时您还应该使用ajaxSelectOptions jqGrid参数来自定义获取选择列表数据的相应$.ajax请求。

方式的优点:

  1. 提供选择列表数据的服务器方法可以有非常清晰的界面,只返回List。
  2. 由于您没有发送&#34; value1&#34;和&#34; text1&#34;两次,因为这些值与您案例中的文本相同。
  3. 如果您的网格使用任何编辑方法(内联,表单或单元格编辑),您可以对editoptions使用相同的方法。在buildSelect的另一个实现中,您应该只跳过在选择列表中插入<option value="">All</option>
  4. 只有在确实需要时才会构建select元素的数据:首次使用搜索。
  5. 服务器对选择列表的HTTP GET响应可以自动缓存,如果您需要在另一个网格中选择相同的数据,则可以直接从本地浏览器缓存中获取以前的服务器响应。