简体   繁体   中英

C# WPF Filter ComboBox based on RadioButtons

I have a WPF project with a Ribbon ComboBox showing a list of countries that I'm trying to filter depending upon a selected RadioButton option (All, Africa, Asia, Europe). I'm basing my code on COMBOBOX filtering in WPF with MVVM which uses a ComboBox to select a continent and show the filtered countries in a ListBox but I'm having trouble converting this to use RadioButtons.

  1. There's a problem with the XAML isChecked="..." lines which appear to cause an 'Input string was not in a correct format' error in the EnumBooleanConverter but if I change them to 'ConverterParameter=0' the app runs. I based this on How to bind RadioButtons to an enum? .
  2. The default list of countries is initially shown in the ComboBox but the default country isn't displayed, instead it's blank.
  3. Clicking on a RadioButton has no effect on the list.

Clearly I'm doing something wrong but I don't know what. Can you help?

XAML:

<ribbon:RibbonRadioButton x:Name="AllContinents"
   GroupName="Continents"
   IsChecked="{Binding Path=SelectedRadioGroup, Converter={StaticResource EnumBooleanConverter}, ConverterParameter={x:Static local:mySettings+Continent.All}}"> <= Causes run error
</ribbon:RibbonRadioButton>

<ribbon:RibbonRadioButton x:Name="Africa"
   GroupName="Continents"
   IsChecked="{Binding Path=SelectedRadioGroup, Converter={StaticResource EnumBooleanConverter}, ConverterParameter={x:Static local:mySettings+Continent.Africa}}"> <= Causes run error
</ribbon:RibbonRadioButton>

C# Code behind (DataContext):

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Data;

public class MySettings : INotifyPropertyChanged
{
    private ObservableCollection<Country> countries;
    private ContinentViewModel selectedContinent;
    public ListCollectionView CountryView { get; set; }
    public event PropertyChangedEventHandler PropertyChanged;
    public ObservableCollection<ContinentViewModel> Continents { get; set; } 
    private static string selectedCountry = "Germany"; // Default country

    public MySettings()
    {
        countries =
            new ObservableCollection<Country>(
                new[]
                    {
                        new Country() { Continent = Continent.Africa, DisplayName = "Algeria" },
                        new Country() { Continent = Continent.Africa, DisplayName = "Egypt" },
                        new Country() { Continent = Continent.Europe, DisplayName = "France" }
                        new Country() { Continent = Continent.Europe, DisplayName = "Germany" }
                    });
        CountryView = new ListCollectionView(countries);
        CountryView.Filter = o => selectedContinent == null || ((Country)o).Continent == selectedContinent.Model;

        Continents = new ObservableCollection<ContinentViewModel>(Enum.GetValues(typeof(Continent)).Cast<Continent>().Select(c => new ContinentViewModel { Model = c}));
    }

    public ListCollectionView CountryView
    {
        get { return countryView; }
        set
        {
            countryView = value;
        }
    }

    public class Country
    {
        public string DisplayName { get; set; }
        public Continent Continent { get; set; }
    }

    public enum Continent
    {
        All,
        Africa,
        Asia,
        Europe,
        America
    }

    public class ContinentViewModel
    {
        public Continent Model { get; set; }
        public string DisplayName
        {
            get
            {
                return Enum.GetName(typeof(Continent), Model);
            }
        }
    }

    public ContinentViewModel SelectedContinent
    {
        get { return selectedContinent; }
        set
        {
            selectedContinent = value;
            OnContinentChanged();
            this.OnPropertyChanged("SelectedContinent");
        }
    }

    private void OnContinentChanged()
    {
        CountryView.Refresh();
    }

    public int SelectedRadioGroup
    {
        get { return selectedRadioGroup; }
        set
        {
            selectedRadioGroup = value;
        }
    }

    public string SelectedCountry
    {
        get { return selectedCountry; }
        set
        {
            if (selectedCountry == value) return;
            selectedCountry = value;
            OnPropertyChanged(nameof(SelectedCountry));
        }
    }

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = this.PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

public class EnumBooleanConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
      int integer = (int)value;
      return integer == int.Parse(parameter.ToString()) ? true : (object)false;  <= Error:Input string was not in a correct format
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return ((bool)value) ? parameter : Binding.DoNothing;
    }
}

I would have a bool property for each radio button rather than using an converter. Then do the check in your filter.

CountryView.Filter += CountryFilter;

private bool _All;
private bool _Africa;
private bool _Asia;
private bool _Europe;
private bool _America;

public bool All { get=>_All; set { _All=value; CountryView.Refresh(); } }
public bool Africa { get=> _Africa; set { _Africa=value; CountryView.Refresh(); } }
public bool Asia { get=> _Asia; set { _Asia=value; CountryView.Refresh(); } }
public bool Europe { get=> _Europe; set { _Europe=value; CountryView.Refresh(); } }
public bool America { get=> _America; set { _America=value; CountryView.Refresh() ;} }}

private bool CountryFilter(object obj)
{
    var country = obj as Country;
    if (country== null) return false;
    if (All) return true;
    if (Africa) return country.Continent == Continent.Africa;
    if (Asia) return country.Continent == Continent.Asia;
    if (Europe) return country.Continent == Continent.Europe;
    if (America) return country.Continent == Continent.America;
    return true;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM