我有一个使用Entity Framework和LINQ的Windows窗体应用程序 有很多形式,我使用BindingNavigator来导航数据,我想在导航器中添加一个textBox来搜索特定的项目并导航到它,我做了一个,但现在我必须做同样的步骤对于其他表单,并在每个表单中添加相同的事件和代码,所以我决定制作一个自定义ToolStripTextBox,我在每个表单中使用它,但我必须使它通用,因为每个表单使用不同的对象或实体,这是什么我想出来:
class ToolStripSearchBox<T> : ToolStripTextBox
{
BindingSource dataSource;
int currentIndex;
public ToolStripSearchBox()
: base()
{
KeyUp += new KeyEventHandler(ToolStripSearchBox_KeyUp);
}
void ToolStripSearchBox_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.F4)
{
string patern = Text;
List<T> TList = dataSource.List.Cast<T>().ToList();
int res = 0;
T foundT = default(T);
if (int.TryParse(patern, out res))
{
foundT = TList.Where(j => j. == res).First();
}
else
{
foundT = TList.First(j => (j.FirstName + " " + j.LastName).Contains(patern));
}
if (foundT == null)
{
return;
}
dataSource.Position = dataSource.IndexOf(foundT);
}
}
}
但问题是每个实体都有不同的属性要过滤,我想使用字符串参数来传递对象属性名称,但我没有找到一种方法将它与LINQ一起使用。
对不起,如果有听写错误,但英语不是我的第一语言 提前致谢
答案 0 :(得分:1)
对于我在您的代码中看到的内容,“每个实体都有不同的属性可以过滤”,您指的是FirstName
,LastName
等属性。
如果是这种情况,很简单,您可以定义一个通用函数对象来用作匹配器。您可以在构造时或初始化期间指定此项。 (我不太喜欢没有参数构造函数的组件。)
class ToolStripSearchBox<T> {
public Func<T, string, bool> Matcher { get; set; }
}
例如,在初始化其中一个用于搜索Foo
的框时,您会这样做:
ToolStripSearchBox<Foo> fooSearchBox = new ToolStripSearchBox<Foo>();
fooSearchBox.Matcher = (j, pattern) => (j.Second + " " + j.Second).Contains(pattern);
也就是说,你的代码存在很多问题:请记住,如果没有找到任何元素,First()
扩展方法将抛出异常;使用FirstOrDefault()
。我看到你也在使用foundT == null
..我怀疑这甚至会编译。请改为foundT == default(T)
。
class ToolStripSearchBox<T> {
void ToolStripSearchBox_KeyUp(object sender, KeyEventArgs e)
{
...
foundT = TList.FirstOrDefault(this.Matcher(j, patern));
...
}
}