none
DataGridViewAutoFilter & DatagridViewComboBoxColumns

    Question

  • Hi,

     

    I've been using the AutoFilter from here:

    http://msdn2.microsoft.com/en-us/library/aa480727.aspx

     

    It works really well. However, there is one thing that is missing and very inconvenient. Can anyone tell me how to make the Filter handle combobox columns differently? Basically, I want to filter combobox columns by DisplayMember - not ValueMember. If anyone has worked out a solution to this, I would be most garteful.

     

    Regards

    Monday, April 14, 2008 11:25 AM

All replies

  • did you get any solution for that ?
    Saturday, February 21, 2009 12:06 AM
  • Better late than never, I guess, right?! I came across this problem as well and had to add some code the DataGridViewAutoFilterColumnHeader class to properly handle combo box columns. I apologize because I've made multiple modifications to the class for my needs, so I can't give you exact line numbers, but  I believe I have adequately indicated where the code blocks need to be inserted. Also, you'll see that I call a ReflectionHelper.GetPropertyValue() method; it is just a static helper class and the method returns a property value given an object and the string property name; you'll need to replace those occurrences with your own version of that functionality. There are two blocks of code, the first goes in the PopulateFilters() method:

    // account for combo box column where a set of text/value items can be displayed; need to translate the values to the text for filter display, and then back against when applying the filter
    if (this.OwningColumn is DataGridViewComboBoxColumn)
    {
    	DataGridViewComboBoxColumn combo = this.OwningColumn as DataGridViewComboBoxColumn;
    	if (combo.DataSource != null)
    	{
    		object holdValue, holdDisplay;
    		if (!String.IsNullOrEmpty(combo.DisplayMember))
    		{
    			foreach (object o in combo.Items)
    			{
    				holdValue = ReflectionHelper.GetPropertyValue(o, (String.IsNullOrEmpty(combo.ValueMember) ? combo.DisplayMember : combo.ValueMember));
    				holdDisplay = ReflectionHelper.GetPropertyValue(o, (String.IsNullOrEmpty(combo.DisplayMember) ? combo.ValueMember : combo.DisplayMember));
    				if (holdValue.Equals(value))
    				{
    					value = holdDisplay;
    					break;
    				}
    			}
    		}
    	}
    	else
    	{
    		foreach (object o in combo.Items)
    		{
    			if (o.Equals(value))
    			{
    				value = o;
    				break;
    			}
    		}
    	}
    }
    It should be inserted in the else of the ICustomTypeDescriptor if/else, immediately after the line that reads:

    value = property.GetValue(item, null /*property index*/);
    That code block will examine the combo box contents and insert the value according to the DisplayMember setting into the list of filter items. I tried to account for non-DataBound combo boxes and also where the DisplayMember or ValueMember property has not been specified. The second code block will do the opposite of the previous code block when a filter item is selected; it will take the filter item text and find the value according to the combo's ValueMember. This code will go into the UpdateFilter() method:

    // handle case where a combo box is supplying values, need to translate the display text back to the actual value for use in comparisons agains the underlying data
    if (this.OwningColumn is DataGridViewComboBoxColumn)
    {
    	DataGridViewComboBoxColumn combo = this.OwningColumn as DataGridViewComboBoxColumn;
    	if (combo.DataSource != null)
    	{
    		object holdValue, holdDisplay;
    		if (!String.IsNullOrEmpty(combo.DisplayMember))
    		{
    			foreach (object o in combo.Items)
    			{
    				holdValue = ReflectionHelper.GetPropertyValue(o, (String.IsNullOrEmpty(combo.ValueMember) ? combo.DisplayMember : combo.ValueMember));
    				holdDisplay = ReflectionHelper.GetPropertyValue(o, (String.IsNullOrEmpty(combo.DisplayMember) ? combo.ValueMember : combo.DisplayMember));
    				if (holdDisplay.Equals(selectedFilterValue))
    				{
    					if (holdValue is String)
    					{
    						newColumnFilter = String.Format("[{0}]='{1}'",
    							columnProperty,
    							((String)holdValue).Replace("'", "''"));
    					}
    					else
    					{
    						newColumnFilter = String.Format("[{0}]={1}",
    							columnProperty,
    							holdValue.ToString());
    					}
    					break;
    				}
    			}
    		}
    	}
    	else
    	{
    		foreach (object o in combo.Items)
    		{
    			if (o.Equals(selectedFilterValue))
    			{
    				if (o is String)
    				{
    					newColumnFilter = String.Format("[{0}]='{1}'",
    						columnProperty,
    						((String)o).Replace("'", "''"));
    				}
    				else
    				{
    					newColumnFilter = String.Format("[{0}]={1}",
    						columnProperty,
    						o.ToString());
    				}
    				break;
    			}
    		}
    	}
    }
    else
    {
    	newColumnFilter = String.Format("[{0}]='{1}'",
    		columnProperty,
    		((String)filters[selectedFilterValue])
    		.Replace("'", "''"));
    }
    This code needs to be inserted in the 'default:' case of the switch statement, this will be the entire code for the default: case of the switch statement, of course add the 'break;' to the end. Hope this helps!
    Saturday, November 21, 2009 9:08 PM
  • I put a project on CodePlex based on the above code. It's at http://dgvautofilter.codeplex.com/

    Wednesday, July 21, 2010 1:39 AM
  • Fix for GUID Columns
    Thanks Dear ryan_aus
    My Project Tables contain GUID as Primary key.
    So 'DataGridViewAutoFilterExtended' doesn't work fine.
    I changed the project to working correctly!

    I Get Latest Version from : http://dgvautofilter.codeplex.com/

    and Change 2 method in file "DataGridViewAutoFilterComboBoxColumn.cs" as bellow:

            public object GetDisplayValue(ICustomTypeDescriptor ictd, object value)
            {
                if (this.DataSource != null)
                {
                    object holdValue, holdDisplay;
                    if (!string.IsNullOrEmpty(this.DisplayMember))
                    {
                        foreach (object o in this.Items)
                        {
                            ICustomTypeDescriptor ic = o as ICustomTypeDescriptor;
                            holdValue = ic.GetProperties().Find((string.IsNullOrEmpty(this.ValueMember) ? this.DisplayMember : this.ValueMember), true).GetValue(ic);
                            holdDisplay = ic.GetProperties().Find((string.IsNullOrEmpty(this.DisplayMember) ? this.ValueMember : this.DisplayMember), true).GetValue(ic);
                            if (holdValue.Equals(value))
                            {
                                return holdDisplay;
                            }
                        }
                    }
                }

                // Return value if we didn't find a match.
                return value;
            }

            public string GetNewFilterValue(string selectedFilterValue, string columnProperty)
            {
                if (this.DataSource != null)
                {
                    object holdValue, holdDisplay;
                    if (!string.IsNullOrEmpty(this.DisplayMember))
                    {
                        foreach (object o in this.Items)
                        {
                            ICustomTypeDescriptor ictd = o as ICustomTypeDescriptor;
                            holdValue = ictd.GetProperties().Find((string.IsNullOrEmpty(this.ValueMember) ? this.DisplayMember : this.ValueMember), true).GetValue(ictd);
                            holdDisplay = ictd.GetProperties().Find((string.IsNullOrEmpty(this.DisplayMember) ? this.ValueMember : this.DisplayMember), true).GetValue(ictd);
                            if (holdDisplay.Equals(selectedFilterValue))
                            {
                                if (holdValue is string || holdValue is System.Guid)
                                {
                                    holdValue = holdValue.ToString();
                                    return string.Format(
                                        "[{0}]='{1}'",
                                        columnProperty,
                                        ((string)holdValue).Replace("'", "''"));
                                }
                                else
                                {
                                    return string.Format(
                                        "[{0}]={1}",
                                        columnProperty,
                                        holdValue.ToString());
                                }
                            }
                        }
                    }
                }
                else
                {
                    foreach (object o in this.Items)
                    {
                        if (o.Equals(selectedFilterValue))
                        {
                            if (o is string)
                            {
                                return string.Format(
                                    "[{0}]='{1}'",
                                    columnProperty,
                                    ((string)o).Replace("'", "''"));
                            }
                            else
                            {
                                return string.Format(
                                    "[{0}]={1}",
                                    columnProperty,
                                    o.ToString());
                            }
                        }
                    }
                }

                // Return the currently selected filter value if we didn't find a match.
                return selectedFilterValue;
            }


    Tuesday, May 29, 2012 3:05 PM