Stopbyte

DevExpress - Why WPF GridControl Column Filtering is not working?

I have a DevExpress GridControl defined in XAML like this:

xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
 
<dxg:GridControl Grid.Row="0" x:Name="clientGrid" DataSource="{Binding ClientsDatasetTable1, UpdateSourceTrigger=PropertyChanged}" AutoExpandAllGroups="True" >
    <dxg:GridControl.TotalSummary>
        <dxg:GridSummaryItem FieldName="TaxpayerName" SummaryType="Count" DisplayFormat="Clients: {0}" />
    </dxg:GridControl.TotalSummary>
 
    <!-- Set the TableView properties -->
    <dxg:GridControl.View>
        <dxg:TableView x:Name="tableView" AllowBestFit="True"
            FocusedRow="{Binding CurrentReturnItem, Mode=TwoWay}"
            EditorButtonShowMode="ShowOnlyInEditor" NavigationStyle="Row" AllowEditing="False"
            MouseDoubleClick="tableView_MouseDoubleClick"
            c:KeyDownHandler.TheCommandToRun="{Binding Path=OpenCommand}" c:KeyDownHandler.Key="Enter" AllowGrouping="False" ShowGroupPanel="False" ShowAutoFilterRow="True" AutoWidth="True" ShowTotalSummary="True"/>
    </dxg:GridControl.View>
 
    <!-- Create the Column collection -->
    <dxg:GridControl.Columns>
        <dxg:GridColumn FieldName="TaxpayerName" Header="Name" ReadOnly="True" Width="150" />
        <dxg:GridColumn FieldName="TaxpayerSsn" Header="SSN" ReadOnly="True" Width="150" />
        <dxg:GridColumn FieldName="ReturnTypeDescription" Header="Return Type" />
        <dxg:GridColumn FieldName="ReturnStatus" Header="Return Status" AutoFilterValue={Binding PageFilterValue} />
    </dxg:GridControl.Columns>
</dxg:GridControl>

The last column is the one i’m intending to Filter on, using the PageFilterValue custom property of my custom page. the property is defined as follows:

public string PageFilterValue
{
    get { return filter_value;}
    set
    {
        filter_value = value;
        OnPropertyChanged("PageFilterValue");
    }
}

The problem now, is the code above works perfect at first time, but once user changes the filter on the GridControl manually the Binding somehow is not working anymore even if the the PageFilterValue is changed.

1 Like

The problem is that you are binding directly from the DevExpress AutoFilterValue property, Once the user manually changes the filter that property Binding gets replaced by the value inputted by user.

so mainly this:

<dxg:GridColumn FieldName="ReturnStatus" Header="Return Status" AutoFilterValue={Binding PageFilterValue} />

Gets replaced by this after user changes the filter:

<dxg:GridColumn FieldName="ReturnStatus" Header="Return Status" AutoFilterValue="Something Inputted by user" />

To solve this you can use a double binding like this:

1. Make a second DependencyProperty in your code behind:

/// <summary>
/// A workaround to allow users to manually filter the GridControl Column
/// </summary>
#region XFilterValueProperty
 
public static readonly DependencyProperty XFilterValueProperty = DependencyProperty.Register(
    "XFilterValue",
    typeof(string),
    typeof(MainWindow), // <-- you should input the appropriate type here.
    new PropertyMetadata(null, XFilterValue_Changed));
public static void XFilterValue_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
    if (sender is MainWindow) // <---
    {
        var mw = sender as MainWindow; // <-- you should use the appropriate type here as well and above, to reflect the container of the targeted DevExpress Grid
        
        /// Here is the trick, so when ever our binded property gets changed through the source property binding the Column filter value will get updated.
        /// That way we make sure that the column will have the latest value either inputted by user, or Set through the binding.
        mw.clientGrid.Columns["Your Targeted Column Field Name"].AutoFilterValue = e.NewValue;
    }
}
 
public string XFilterValue
{
    get { return (string)GetValue(XFilterValueProperty); }
    set { SetValue(XFilterValueProperty, value); }
}
 
#endregion

2. Add a custom Binding from your Source property to the Property above:

// Register a binding to our filtering value, that way we can avoid that the binding will get erased (replaced)
// when user manually sets different filter.
SetBinding(XFilterValueProperty, new Binding() { Path = new PropertyPath("Your Source property name"), Source=YourSourceObjectHere });