Below is an example of a class that, searches an item in a DataGrid
for text matches in it's property values. I currently call it with:
FullTextSearchNext<UserViewModel>.FullTextSearchInit();
The <UserViewModel>
hardcoded above is what the ItemsSource
in my DataGrid
consists of. To clarify: the collection is made up of UserViewModel
items.
What I am wondering is, is there a way I can get the item class (UserViewModel
) from the DataGrid
and replace the hardcoded <UserViewModel>
with a variable of some sort? Thus making my calls to the ClassPropertySearch
generic as well as the class itself.
public static class ClassPropertySearch<T>
{
public static bool Match(T item, string searchTerm)
{
bool match = _properties.Select(prop => prop(item)).Any(value => value != null && value.ToLower().Contains(searchTerm.ToLower()));
return match;
}
private static List<Func<T, string>> _properties;
public static void FullTextSearchInit()
{
_properties = GetPropertyFunctions().ToList();
}
}
[EDIT]
This is to show more of the class, which I should have done initially.
Includes Marius'solution:
Now that <T> is removed from ClassPropertySearch the other functions such as GetPropertyFunctions, etc, do not work , should I just pass the type through to them as parameters?
public static class ClassPropertySearch
{
public static bool Match(Type itemType, string searchTerm)
{
bool match = _properties.Select(prop => prop(itemType)).Any(value => value != null && value.ToLower().Contains(searchTerm.ToLower()));
return match;
}
private static List<Func<Type, string>> _properties;
public static void FullTextSearchInit(List<string> binding_properties)
{
_properties = GetPropertyFunctions().ToList();
}
public static IEnumerable<Func<Type, string>> GetPropertyFunctions()
{
return GetStringPropertyFunctions();
}
public static IEnumerable<Func<Type, string>> GetStringPropertyFunctions()
{
var propertyInfos = typeof(Type).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.SetProperty)
.Where(p => p.PropertyType == typeof(string)).ToList();
var properties = propertyInfos.Select(GetStringPropertyFunc);
return properties;
}
public static Func<Type, string> GetStringPropertyFunc(PropertyInfo propInfo)
{
ParameterExpression x = System.Linq.Expressions.Expression.Parameter(typeof(Type), "x");
Expression<Func<Type, string>> expression = System.Linq.Expressions.Expression.Lambda<Func<Type, string>>(System.Linq.Expressions.Expression.Property(x, propInfo), x);
Func<Type, string> propertyAccessor = expression.Compile();
return propertyAccessor;
}
}
You could replace the generic type T
with type Type
.
public static class ClassPropertySearch
{
public static bool Match(Type itemType, string searchTerm)
{
bool match = _properties.Select(prop => prop(itemType)).Any(value => value != null && value.ToLower().Contains(searchTerm.ToLower()));
return match;
}
private static List<Func<Type, string>> _properties;
public static void FullTextSearchInit()
{
_properties = GetPropertyFunctions().ToList();
}
}
So instead of passing the UserViewModel
you would pass typeof(UserViewModel)
. Of course, since you need this at runtime, you need to say obj.GetType()
.