- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我最初将 DGV 的数据源设置为 SortableBindingList。当我运行该程序时,我可以单击任何列标题并按列升序或降序排序。
我已经实现了一个过滤器文本框,它使用 LINQ 过滤 DGV 中的数据。在我使用 LINQ 过滤列表之后。我将筛选后的列表重新绑定(bind)到 DGV,但之前排序的列不再排序。
即使我重新绑定(bind)了一个新的数据源,DGV 是否应该继续排序?
为此,我想到的唯一解决方法是将当前的 SortedColumn 索引和当前的 SortOrder 存储到变量中,然后在绑定(bind)新数据源时重置这些属性。
private void PopulateGrid()
{
var gridSource = new MySortableBindingList<Case>(_caseList);
dataGridView_Cases.DataSource = gridSource;
ConfigureGrid();
}
private void ApplyFilter(string fString)
{
MySortableBindingList<Case> msbList = new MySortableBindingList<Case>(_caseList.Where(x => (x.StudentLastName.IndexOf(fString, StringComparison.OrdinalIgnoreCase) >= 0) || (x.StudentIDDisplay.ToString().IndexOf(fString, StringComparison.OrdinalIgnoreCase) >= 0)).ToList());
dataGridView_Cases.DataSource = msbList;
}
更新 1:(新代码)
private MySortableBindingList<Case> _gridSource = new MySortableBindingList<Case>();
BindingSource _caseBindingSource = new BindingSource();
private void PopulateGrid()
{
_gridSource = new MySortableBindingList<Case>(_caseList);
_caseBindingSource.DataSource = _gridSource;
dataGridView_Cases.DataSource = _caseBindingSource;
ConfigureGrid();
}
private void ApplyFilter(string fString)
{
_gridSource.Clear();
foreach (var fCase in _caseList.Where(x => (x.StudentLastName.IndexOf(fString, StringComparison.OrdinalIgnoreCase) >= 0) || (x.StudentIDDisplay.ToString().IndexOf(fString, StringComparison.OrdinalIgnoreCase) >= 0)).ToList())
{
_gridSource.Add(fCase);
}
_caseBindingSource.ResetBindings(false);
}
更新 2:(附加代码)
/// <summary>
/// Source: http://www.codeproject.com/Articles/31418/Implementing-a-Sortable-BindingList-Very-Very-Quic
/// </summary>
/// <typeparam name="T"></typeparam>
public class MySortableBindingList<T> : BindingList<T>
{
// reference to the list provided at the time of instantiation
List<T> originalList;
ListSortDirection sortDirection;
PropertyDescriptor sortProperty;
// function that refereshes the contents
// of the base classes collection of elements
Action<MySortableBindingList<T>, List<T>>
populateBaseList = (a, b) => a.ResetItems(b);
// a cache of functions that perform the sorting
// for a given type, property, and sort direction
static Dictionary<string, Func<List<T>, IEnumerable<T>>>
cachedOrderByExpressions = new Dictionary<string, Func<List<T>,
IEnumerable<T>>>();
/// <summary>
/// Create a sortable binding list
/// </summary>
public MySortableBindingList()
{
originalList = new List<T>();
}
/// <summary>
/// Create a sortable binding list
/// </summary>
public MySortableBindingList(IEnumerable<T> enumerable)
{
originalList = enumerable.ToList();
populateBaseList(this, originalList);
}
/// <summary>
/// Create a sortable binding list
/// </summary>
public MySortableBindingList(List<T> list)
{
originalList = list;
populateBaseList(this, originalList);
}
/// <summary>
/// Look for an appropriate sort method in the cache if not found .
/// Call CreateOrderByMethod to create one.
/// Apply it to the original list.
/// Notify any bound controls that the sort has been applied.
/// </summary>
/// <param name="prop"></param>
/// <param name="direction"></param>
protected override void ApplySortCore(PropertyDescriptor prop,
ListSortDirection direction)
{
/*
Look for an appropriate sort method in the cache if not found .
Call CreateOrderByMethod to create one.
Apply it to the original list.
Notify any bound controls that the sort has been applied.
*/
sortProperty = prop;
var orderByMethodName = sortDirection ==
ListSortDirection.Ascending ? "OrderBy" : "OrderByDescending";
var cacheKey = typeof(T).GUID + prop.Name + orderByMethodName;
if (!cachedOrderByExpressions.ContainsKey(cacheKey))
{
CreateOrderByMethod(prop, orderByMethodName, cacheKey);
}
ResetItems(cachedOrderByExpressions[cacheKey](originalList).ToList());
ResetBindings();
sortDirection = sortDirection == ListSortDirection.Ascending ?
ListSortDirection.Descending : ListSortDirection.Ascending;
}
private void CreateOrderByMethod(PropertyDescriptor prop,
string orderByMethodName, string cacheKey)
{
/*
Create a generic method implementation for IEnumerable<T>.
Cache it.
*/
var sourceParameter = Expression.Parameter(typeof(List<T>), "source");
var lambdaParameter = Expression.Parameter(typeof(T), "lambdaParameter");
var accesedMember = typeof(T).GetProperty(prop.Name);
var propertySelectorLambda =
Expression.Lambda(Expression.MakeMemberAccess(lambdaParameter,
accesedMember), lambdaParameter);
var orderByMethod = typeof(Enumerable).GetMethods()
.Where(a => a.Name == orderByMethodName &&
a.GetParameters().Length == 2)
.Single()
.MakeGenericMethod(typeof(T), prop.PropertyType);
var orderByExpression = Expression.Lambda<Func<List<T>, IEnumerable<T>>>(
Expression.Call(orderByMethod,
new Expression[] { sourceParameter,
propertySelectorLambda }),
sourceParameter);
cachedOrderByExpressions.Add(cacheKey, orderByExpression.Compile());
}
/// <summary>
/// RemoveSortCore
/// </summary>
protected override void RemoveSortCore()
{
ResetItems(originalList);
}
private void ResetItems(List<T> items)
{
base.ClearItems();
for (int i = 0; i < items.Count; i++)
{
base.InsertItem(i, items[i]);
}
}
/// <summary>
/// SupportsSortingCore
/// </summary>
protected override bool SupportsSortingCore
{
get
{
// indeed we do
return true;
}
}
/// <summary>
/// Ascending or descending
/// </summary>
protected override ListSortDirection SortDirectionCore
{
get
{
return sortDirection;
}
}
/// <summary>
/// A property
/// </summary>
protected override PropertyDescriptor SortPropertyCore
{
get
{
return sortProperty;
}
}
/// <summary>
/// List has changed
/// </summary>
/// <param name="e"></param>
protected override void OnListChanged(ListChangedEventArgs e)
{
originalList = base.Items.ToList();
}
}
最佳答案
DataGridView
不包含自己的排序功能,而是依赖数据源来执行此操作,更具体地说是 IBindingList
执行。除排序外,IBindingList
提供一个 ListChanged
可用于更新附加到它的任何 UI 的事件。注意 IBindingList
也是一个列表,即您可以像普通列表一样添加/删除/更新项目,因此您不需要创建新列表并将其重新分配为数据源。相反,创建它一次,将 UI 附加到它,然后随时更新列表内容,UI 将自动反射(reflect)更改 - 数据绑定(bind)“魔法”之一。
现在,为了让这一切发生,IBindingList
必须正确实现。 BindingList<T>
已经提供了大部分所需的功能,但不幸的是,它不包括排序。您遇到的问题源于您使用的是有问题的第三方组件(通常没有标准组件)。
所以,而不是 MySortableBindindingList<T>
使用以下实现:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
namespace Tests
{
public class MyBindingList<T> : BindingList<T>
{
static readonly Dictionary<string, Func<IEnumerable<T>, IEnumerable<T>>> orderByMethodCache = new Dictionary<string, Func<IEnumerable<T>, IEnumerable<T>>>();
private static Func<IEnumerable<T>, IEnumerable<T>> GetOrderByMethod(PropertyDescriptor prop, ListSortDirection direction)
{
var orderByMethodName = direction == ListSortDirection.Ascending ? "OrderBy" : "OrderByDescending";
var cacheKey = typeof(T).GUID + prop.Name + orderByMethodName;
Func<IEnumerable<T>, IEnumerable<T>> orderByMethod;
if (!orderByMethodCache.TryGetValue(cacheKey, out orderByMethod))
orderByMethodCache.Add(cacheKey, orderByMethod = CreateOrderByMethod(prop, orderByMethodName));
return orderByMethod;
}
private static Func<IEnumerable<T>, IEnumerable<T>> CreateOrderByMethod(PropertyDescriptor prop, string orderByMethodName)
{
var source = Expression.Parameter(typeof(IEnumerable<T>), "source");
var item = Expression.Parameter(typeof(T), "item");
var member = Expression.Property(item, prop.Name);
var selector = Expression.Lambda(member, item);
var orderByMethod = typeof(Enumerable).GetMethods()
.Single(a => a.Name == orderByMethodName && a.GetParameters().Length == 2)
.MakeGenericMethod(typeof(T), member.Type);
var orderByExpression = Expression.Lambda<Func<IEnumerable<T>, IEnumerable<T>>>(
Expression.Call(orderByMethod, new Expression[] { source, selector }), source);
return orderByExpression.Compile();
}
List<T> originalList = new List<T>();
ListSortDirection sortDirection;
PropertyDescriptor sortProperty;
bool isSorted;
bool ignoreListChanged;
Func<T, bool> filter;
public MyBindingList() { }
public MyBindingList(IEnumerable<T> items) { Update(items); }
protected override bool SupportsSortingCore { get { return true; } }
protected override PropertyDescriptor SortPropertyCore { get { return sortProperty; } }
protected override ListSortDirection SortDirectionCore { get { return sortDirection; } }
protected override bool IsSortedCore { get { return isSorted; } }
public Func<T, bool> Filter
{
get { return filter; }
set
{
filter = value;
Refresh();
}
}
public void Update(IEnumerable<T> items)
{
originalList.Clear();
originalList.AddRange(items);
Refresh();
}
public void Refresh()
{
var items = originalList.AsEnumerable();
if (Filter != null)
items = items.Where(filter);
if (isSorted)
items = GetOrderByMethod(sortProperty, sortDirection)(items);
bool raiseListChangedEvents = RaiseListChangedEvents;
RaiseListChangedEvents = false;
base.ClearItems();
foreach (var item in items)
Add(item);
RaiseListChangedEvents = raiseListChangedEvents;
if (!raiseListChangedEvents) return;
ignoreListChanged = true;
ResetBindings();
ignoreListChanged = false;
}
protected override void OnListChanged(ListChangedEventArgs e)
{
if (!ignoreListChanged)
originalList = Items.ToList();
base.OnListChanged(e);
}
protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
{
var orderByMethod = GetOrderByMethod(prop, direction);
sortProperty = prop;
sortDirection = direction;
isSorted = true;
Refresh();
}
protected override void RemoveSortCore()
{
if (!isSorted) return;
isSorted = false;
Refresh();
}
}
}
还支持替换内容和用户定义的过滤器。
这是一个如何使用它的例子,只是为了了解这个想法,但我想你可以很容易地将它映射到你的特定需求:
using System;
using System.Windows.Forms;
namespace Tests
{
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var form = new Form();
var dg = new DataGridView { Dock = DockStyle.Fill, Parent = form };
var filterBox = new TextBox { Dock = DockStyle.Bottom, Parent = form };
var data = new MyBindingList<Person>(new[]
{
new Person { FirstName = "Jon", LastName = "Skeet" },
new Person { FirstName = "Hans", LastName = "Passant" },
new Person { FirstName = "Ivan", LastName = "Stoev" },
});
dg.DataSource = data;
var filterText = string.Empty;
filterBox.TextChanged += (sender, e) =>
{
var text = filterBox.Text.Trim();
if (filterText == text) return;
filterText = text;
if (!string.IsNullOrEmpty(filterText))
data.Filter = person => person.FirstName.Contains(filterText) || person.LastName.Contains(filterText);
else
data.Filter = null;
};
Application.Run(form);
}
}
}
关于C# Winforms DataGridView 绑定(bind)新数据源时排序列丢失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33132999/
SQLite、Content provider 和 Shared Preference 之间的所有已知区别。 但我想知道什么时候需要根据情况使用 SQLite 或 Content Provider 或
警告:我正在使用一个我无法完全控制的后端,所以我正在努力解决 Backbone 中的一些注意事项,这些注意事项可能在其他地方更好地解决......不幸的是,我别无选择,只能在这里处理它们! 所以,我的
我一整天都在挣扎。我的预输入搜索表达式与远程 json 数据完美配合。但是当我尝试使用相同的 json 数据作为预取数据时,建议为空。点击第一个标志后,我收到预定义消息“无法找到任何内容...”,结果
我正在制作一个模拟 NHL 选秀彩票的程序,其中屏幕右侧应该有一个 JTextField,并且在左侧绘制弹跳的选秀球。我创建了一个名为 Ball 的类,它实现了 Runnable,并在我的主 Draf
这个问题已经有答案了: How can I calculate a time span in Java and format the output? (18 个回答) 已关闭 9 年前。 这是我的代码
我有一个 ASP.NET Web API 应用程序在我的本地 IIS 实例上运行。 Web 应用程序配置有 CORS。我调用的 Web API 方法类似于: [POST("/API/{foo}/{ba
我将用户输入的时间和日期作为: DatePicker dp = (DatePicker) findViewById(R.id.datePicker); TimePicker tp = (TimePic
放宽“邻居”的标准是否足够,或者是否有其他标准行动可以采取? 最佳答案 如果所有相邻解决方案都是 Tabu,则听起来您的 Tabu 列表的大小太长或您的释放策略太严格。一个好的 Tabu 列表长度是
我正在阅读来自 cppreference 的代码示例: #include #include #include #include template void print_queue(T& q)
我快疯了,我试图理解工具提示的行为,但没有成功。 1. 第一个问题是当我尝试通过插件(按钮 1)在点击事件中使用它时 -> 如果您转到 Fiddle,您会在“内容”内看到该函数' 每次点击都会调用该属
我在功能组件中有以下代码: const [ folder, setFolder ] = useState([]); const folderData = useContext(FolderContex
我在使用预签名网址和 AFNetworking 3.0 从 S3 获取图像时遇到问题。我可以使用 NSMutableURLRequest 和 NSURLSession 获取图像,但是当我使用 AFHT
我正在使用 Oracle ojdbc 12 和 Java 8 处理 Oracle UCP 管理器的问题。当 UCP 池启动失败时,我希望关闭它创建的连接。 当池初始化期间遇到 ORA-02391:超过
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 9 年前。 Improve
引用这个plunker: https://plnkr.co/edit/GWsbdDWVvBYNMqyxzlLY?p=preview 我在 styles.css 文件和 src/app.ts 文件中指定
为什么我的条形这么细?我尝试将宽度设置为 1,它们变得非常厚。我不知道还能尝试什么。默认厚度为 0.8,这是应该的样子吗? import matplotlib.pyplot as plt import
当我编写时,查询按预期执行: SELECT id, day2.count - day1.count AS diff FROM day1 NATURAL JOIN day2; 但我真正想要的是右连接。当
我有以下时间数据: 0 08/01/16 13:07:46,335437 1 18/02/16 08:40:40,565575 2 14/01/16 22:2
一些背景知识 -我的 NodeJS 服务器在端口 3001 上运行,我的 React 应用程序在端口 3000 上运行。我在 React 应用程序 package.json 中设置了一个代理来代理对端
我面临着一个愚蠢的问题。我试图在我的 Angular 应用程序中延迟加载我的图像,我已经尝试过这个2: 但是他们都设置了 src attr 而不是 data-src,我在这里遗漏了什么吗?保留 d
我是一名优秀的程序员,十分优秀!