Question

I have a DataGrid that displays only certain properties of a class.

What I would like to do is, get a List of the bound properties in column order, how can I achieve this?

One more thing, I would only want the visible columns.

[EDIT]

The following is what I use to search for text within class properties, at the moment it searches through all properties.

This will change to search for only properties that are visible on the DataGrid

public static class FullTextSearch<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();
    }

    public static IEnumerable<Func<T, string>> GetPropertyFunctions()
    {
        var stringProperties = GetStringPropertyFunctions();
        var intProperties = GetIntPropertyFunctions();
        var decimalProperties = GetDecimalPropertyFunctions();
        var dateTimeProperties = GetDateTimePropertyFunctions();
        return stringProperties.Concat(decimalProperties).Concat(intProperties).Concat(dateTimeProperties);
    }

    public static IEnumerable<Func<T, string>> GetStringPropertyFunctions()
    {
        var propertyInfos = typeof(T).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<T, string> GetStringPropertyFunc(PropertyInfo propInfo)
    {
        ParameterExpression x = System.Linq.Expressions.Expression.Parameter(typeof(T), "x");
        Expression<Func<T, string>> expression = System.Linq.Expressions.Expression.Lambda<Func<T, string>>(System.Linq.Expressions.Expression.Property(x, propInfo), x);
        Func<T, string> propertyAccessor = expression.Compile();
        return propertyAccessor;
    }

    public static IEnumerable<Func<T, string>> GetIntPropertyFunctions()
    {
        var propertyInfos = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.SetProperty)
            .Where(p => p.PropertyType == typeof(int)).ToList();

        var properties = propertyInfos.Select(GetIntPropertyFunc);
        return properties;
    }

    public static Func<T, string> GetIntPropertyFunc(PropertyInfo propInfo)
    {
        ParameterExpression x = System.Linq.Expressions.Expression.Parameter(typeof(T), "x");
        Expression<Func<T, int>> expression = System.Linq.Expressions.Expression.Lambda<Func<T, int>>(System.Linq.Expressions.Expression.Property(x, propInfo), x);
        Func<T, int> propertyAccessor = expression.Compile();
        return (T item) => propertyAccessor(item).ToString();
    }

    public static IEnumerable<Func<T, string>> GetDecimalPropertyFunctions()
    {
        var propertyInfos = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.SetProperty)
            .Where(p => p.PropertyType == typeof(decimal)).ToList();

        var properties = propertyInfos.Select(GetDecimalPropertyFunc);
        return properties;
    }

    public static Func<T, string> GetDecimalPropertyFunc(PropertyInfo propInfo)
    {
        ParameterExpression x = System.Linq.Expressions.Expression.Parameter(typeof(T), "x");
        Expression<Func<T, decimal>> expression = System.Linq.Expressions.Expression.Lambda<Func<T, decimal>>(System.Linq.Expressions.Expression.Property(x, propInfo), x);
        Func<T, decimal> propertyAccessor = expression.Compile();
        return (T item) => propertyAccessor(item).ToString();
    }

    public static IEnumerable<Func<T, string>> GetDateTimePropertyFunctions()
    {
        var propertyInfos = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.SetProperty)
            .Where(p => p.PropertyType == typeof(DateTime)).ToList();

        var properties = propertyInfos.Select(GetDateTimePropertyFunc);
        return properties;
    }

    public static Func<T, string> GetDateTimePropertyFunc(PropertyInfo propInfo)
    {
        ParameterExpression x = System.Linq.Expressions.Expression.Parameter(typeof(T), "x");
        Expression<Func<T, DateTime>> expression = System.Linq.Expressions.Expression.Lambda<Func<T, DateTime>>(System.Linq.Expressions.Expression.Property(x, propInfo), x);
        Func<T, DateTime> propertyAccessor = expression.Compile();
        return (T item) => propertyAccessor(item).ToString();
    }
}

The code below is how I call it, it finds all the properties that match the search value and add the items to a list, this list is processed and added to the SelectedItems property on the DataGrid.

In the long run I would like to make this generic enough to have on any DataGrid. So instead of searching through all properties, it needs to get more specific and if I want to provide next and previous search functionality, to go to the next or previous cell match I need to get these properties in the order that matches the DataGrid columns.

Eventually I'd like to remove the hard-coded class name when I call:
FullTextSearch<UserViewModel>.FullTextSearchInit();
and
FullTextSearch<UserViewModel>.Match()
but this will be another question

string sv = SearchValue;
this.Target.SelectedItems.Clear();

var itemsSource = this.Target.Items as IEnumerable;

List<Object> tempItems = new List<Object>();

FullTextSearch<UserViewModel>.FullTextSearchInit();

if (itemsSource != null)
{
    foreach (var item in itemsSource)
    {
        if (FullTextSearch<UserViewModel>.Match((UserViewModel)item, sv))
        {
            tempItems.Add(item);
        }
    }
    if (tempItems.Count > 0)
    {
        //Add found items to SelectedItems
    }
}
Was it helpful?

Solution

I'm not sure if this helps:

var visibleColumns = grid.Columns.Where(c => c.Visibility == System.Windows.Visibility.Visible).ToList();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top