Click here to Skip to main content
15,890,512 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am working with a DataTable containing Skill objects that describe skills in a larp I play. The skills original come from a nosql database. I am displaying that data in a DataGridView . Essentially i want to have a text box you can enter a filter in and have the DataGridView display any row that has ANY field containing your filter text.

So for example
Name              Short Description      Tier  Category  Tags
Avoid             dodge Bullets          Basic Combat    nopes, combat
Basic Projectile  Allows use of firearms Basic Combat    combat, firearms


Using the above data, if you typed 'firearms' into your filter. You would get a single row containing 'Basic Projectile'. If you typed in combat, you would get both Avoid and Basic Projectile (because of the Category and the tags)

I even have a extension method for DataTable that writes up the exact filter text based on the text you enter. It even works.

Except that one field 'Tags'. The underlying structure containing those tags on the class is actually a List<string>. I am formatting it in the CellFormatting event of the DataGridView and while the List<string> displays correctly in the DataGridView I cannot get anything to filter on those tags even using CONVERT(), Like, Contains and so forth. All the rest of the fields work just fine but I'm guessing that tags field isn't returning anything or its returning the ToString() value of the field and it ends up being System.Collections.Generic.List<skill> rather than the list of tags.

I love LINQ but I am trying to do this via the RowFilter on the DefaultView of the DataTable because i can generate a string based on user input.

I've seen many applications both desktop and web based that do this so I know it's possible. I'm just not sure why it's not working in this instance.

The property in question is below (all the rest work just fine). It has a converter attached but it doesn't appear to ever get called.
C#
private List tags;
[TypeConverter(typeof(StringListConverter))]
public List Tags
{
    get { return this.tags; }
    set
    {
        if (value != this.tags)
        {
            this.tags = value;
            NotifyPropertyChanged();
        }
    }
}


C#
public class StringListConverter : TypeConverter
{
    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        if (value is List)
        {
            return string.Join(" ", value);
        }
        return base.ConvertFrom(context, culture, value);
    }
}


Does anyone have any idea how to filter on a property containing a string list?

What I have tried:

The extension method is currently generating the following string:

Convert(Id, 'System.String') Like '%nope%' OR Convert(Name, 'System.String') Like '%nope%' OR Convert(Description, 'System.String') Like '%nope%' OR Convert(ShortDescription, 'System.String') Like '%nope%' OR Convert(SkillCategory, 'System.String') Like '%nope%' OR Convert(SkillTier, 'System.String') Like '%nope%' OR Convert(Tags, 'System.String') Like '%nope%'
Posted
Updated 25-Jun-19 8:23am
Comments
Eiredrake 25-Jun-19 14:09pm    
Convert must be using ToString() to convert. If I search for 'System', 'Generic' or 'List' I get both items neither of which contain any of those terms.

1 solution

Ok so... this is a bit of a hack and still doesn't explain what's going on. But I can now search on the tags.

first, I added a side effect property on the Skills class which forces a correct transform from a List<string> to a comma delimited string..

C#
public string TagString
        {
            get
            {
                return string.Join(", ", this.tags);
            }
        }


Then I changed the DataGridViewTextBoxColumn to point to TagString instead of Tags.
C#
this.tagsColumn             = new DataGridViewTextBoxColumn() { DataPropertyName = "TagString", HeaderText = "Tags", AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells };


then I removed the CellFormatting event

C#
private void SkillListView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
    //if (sender is DataGridView dataGridView)
    //{
    //    if (e.ColumnIndex == this.tagsColumn.Index)
    //    {
    //        if (e.Value is List<string> stringList)
    //        {
    //            e.Value = string.Join(", ", stringList);
    //            e.FormattingApplied = true;
    //        }
    //    }
    //}
}


now if I search for 'nopes' I only get Avoid.

However, if I search for 'System' 'Generic' or 'String' I still get both items.

Oh well it's just a test harness anyway.


If you guys have any other suggestions I'd still love to hear them.
 
Share this answer
 
Comments
Maciej Los 26-Jun-19 14:51pm    
Does not sound like an answer, but like a second part of a question...

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900