Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Usage of GlobalFilter #51

Closed
abid76 opened this issue Feb 11, 2021 · 4 comments
Closed

Usage of GlobalFilter #51

abid76 opened this issue Feb 11, 2021 · 4 comments

Comments

@abid76
Copy link

abid76 commented Feb 11, 2021

Hi all,

I would like to implement a TextBox placed above the data grid where the user can search globally in the data grid.

I wonder if/how to use GlobalFilter for this.

I tried binding a Predicate to the GlobalFilter property. But the Predicate is evaluated only first time the data grid shows up.

Is there a way to apply the Predicate each time the text in the global search TextBox changes?

Or do I misunderstand the purpose of GlobalFilter?

Regards

@abid76
Copy link
Author

abid76 commented Feb 12, 2021

I finally found it out. Problem was, that firing PropertyChangedEvent on GlobalFilter had no effect.

I solved it by setting GlobalFilter to null and then back to the predicate.

View:

<TextBox Text="{Binding GlobalFilterText, UpdateSourceTrigger=PropertyChanged}" />
<DataGrid dgx:DataGridFilter.GlobalFilter="{Binding GlobalFilter}">
  <DataGrid.Columns>
    <!-- .... -->
  </DataGrid.Columns>
</DataGrid>

ViewModel:

private string globalFilterText;
public string GlobalFilterText
{
    get => globalFilterText;
    set 
    { 
        if (Set(ref globalFilterText, value))
        {
            // OnPropertyChanged(() => GlobalFilter); commented out as it has no effect.
            GlobalFilter = null;
            GlobalFilter = ApplyGlobalFilter;
        }
    }
}

protected virtual bool ApplyGlobalFilter(object obj)
{
    // apply the filtering
}

@tom-englert
Copy link
Collaborator

😃

@mdomas1
Copy link

mdomas1 commented Mar 18, 2021

Hello @abid76 ,
Would you mind sharing your full C# code for getting the Global Filter to work? I am struggling as well. I just want to be able to have a textbox with a keyword that filters the rows of my datagrid. Unfortunately, I cannot use the AutoFilter as the way I databind isn't compatible, but I believe if I do a custom Global Filter it should work.

@abid76
Copy link
Author

abid76 commented Mar 18, 2021

@mdomas1
MyListView.xaml:

<UserControl x:Class="MyListView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:dgx="urn:tom-englert.de/DataGridExtensions">
   <DockPanel>
        <TextBox DockPanel.Dock="Top" Text="{Binding GlobalFilterText, UpdateSourceTrigger=PropertyChanged}" />
        <DataGrid 
                  ItemsSource="{Binding ItemListView}" dgx:DataGridFilter.GlobalFilter="{Binding GlobalFilter}">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Title" Binding="{Binding Title}" />
                <DataGridTextColumn Header="User"  Binding="{Binding Username}" />
                <!-- ... -->
            </DataGrid.Columns>
        </DataGrid>
</UserControl>

MyListViewModel.cs:

public class MyListViewModel : ViewModelBase
{
    public ListCollectionView ItemListView { get; set; } // Collection of MyListItem items

    private string globalFilterText;
    public string GlobalFilterText
    {
        get => globalFilterText;
        set 
        {  
            if (Set(ref globalFilterText, value))
            {
                GlobalFilter = null;
                GlobalFilter = ApplyGlobalFilter;
            }
        }
    }

    protected override bool ApplyGlobalFilter(object obj)
    {
            var text = GlobalFilterText?.Trim();
            if (string.IsNullOrEmpty(text))
                return true;

            var terms = Regex.Split(text, @"\s+");

            var item = obj as MyListItem;
            return
                terms.All(term =>
                {
                    // filter on displayed properties (columns) of MyListItem
                    item.Title.Contains(term, StringComparison.OrdinalIgnoreCase) ||
                    item.Username.Contais(term, StringComparison.OrdinalIgnoreCase);
                });
    }
}

ViewModelBase.cs

public abstract class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected bool Set<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
        {
            if (Equals(storage, value)) return false;

            storage = value;
            OnPropertyChanged(propertyName);
            return true;
        }

        private bool Equals<TKey, TValue>(Dictionary<TKey, TValue> dict1, Dictionary<TKey, TValue> dict2)
        {
            bool equal = false;
            if (dict1.Count == dict2.Count)
            {
                equal = true;
                foreach (var pair in dict1)
                {
                    TValue value;
                    if (dict2.TryGetValue(pair.Key, out value))
                    {
                        // Require value be equal.
                        if (!Equals(pair.Value, value))
                        {
                            equal = false;
                            break;
                        }
                    }
                    else
                    {
                        // Require key be present.
                        equal = false;
                        break;
                    }
                }
            }
            return equal;
        }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants