Search code examples
c#wpflistviewmvvmdata-binding

In WPF, displaying only empty fields


In WPF, I have a ListView which is bounded to a Dictionary (InpLangList) and a CheckBox bounded with a boolean(IsShowEmptyFields) property.

Eg. private Dictionary<string, string> _langList = new Dictionary<string, string>();

<ListView ItemsSource="{Binding InpLangList, Mode=TwoWay}" >
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Id" Width="Auto" DisplayMemberBinding="{Binding Key}" />
            <GridViewColumn Header="Values" Width="Auto" DisplayMemberBinding="{Binding Value}" />
        </GridView>
    </ListView.View>
</ListView>

public Dictionary<string, string> InpLangList
{
    get { return _langList ; }
    set
    {
        _langList = value; 
        NotifyPropertyChanged();
    }
}

(...)

InpLangList.Add("id1","One");
InpLangList.Add("id2","");
InpLangList.Add("id3","");
InpLangList.Add("id4","Four");
InpLangList.Add("id5","Five");

(...)

private bool _isShowEmptyFields;

public bool IsShowEmptyFields
{
    get { return _isShowEmptyFields; }
    set
    {
        _isShowEmptyFields = value; 
        NotifyPropertyChanged();
    }
}

What I need is, if Checkbox is checked, then I want to display only the empty fields, i.e.

InpLangList.Add("id2","");
InpLangList.Add("id3","");

should be displayed in the ListView else entire InpLangList should be displayed in the ListView.


Solution

  • Use CollectionView:

    ViewModel:

    // Actual data source
    Dictionary<string, string> inpLangList = new Dictionary<string, string>();
    // A presentation of your data that you can group, sort, filter, etc
    public ICollectionView InpLangList { get; set; }
    
    private bool _isShowEmptyFields;
    public bool IsShowEmptyFields 
    {
        get { return _isShowEmptyFields; }
        set 
        {
            _isShowEmptyFields = value;
            // if the presentation of your data is assigned - filter it
            InpLangList?.Refresh();
        }
    }
    
    // ViewModel constructor
    public VM()
    {
        inpLangList.Add("id1", "One");
        inpLangList.Add("id2", "");
        inpLangList.Add("id3", "");
        inpLangList.Add("id4", "Four");
        inpLangList.Add("id5", "Five");
        // note what's going next:
        // assigning the data source to it's presentation (view)
        InpLangList = CollectionViewSource.GetDefaultView(inpLangList);
        // assigning filter that will be applied to your data source
        // before the showing it within the UI
        InpLangList.Filter = (obj) => 
        {
            if (!(obj is KeyValuePair<string, string> pair))
                return false;
             return !IsShowEmptyFields || string.IsNullOrEmpty(pair.Value);
        };
    }
    

    View:

    <CheckBox IsChecked="{Binding IsShowEmptyFields}" Content="Empty only"/>
    <ListView ItemsSource="{Binding InpLangList}" >
        <ListView.View>
             <GridView>
                <GridViewColumn Header="Id" Width="Auto" DisplayMemberBinding="{Binding Key}" />
                <GridViewColumn Header="Values" Width="Auto" DisplayMemberBinding="{Binding Value}" />
            </GridView>
        </ListView.View>
    </ListView>