【问题标题】:C# WPF Filter ComboBox based on RadioButtons基于 RadioButtons 的 C# WPF 过滤器组合框
【发布时间】:2020-01-17 02:02:34
【问题描述】:

我有一个带有功能区组合框的 WPF 项目,其中显示了我尝试根据选定的 RadioButton 选项(全部、非洲、亚洲、欧洲)过滤的国家/地区列表。我的代码基于 COMBOBOX filtering in WPF with MVVM,它使用 ComboBox 选择大陆并在 ListBox 中显示过滤后的国家/地区,但我无法将其转换为使用 RadioButtons。

  1. XAML isChecked="..." 行存在问题,这似乎会导致 EnumBooleanConverter 中出现“输入字符串格式不正确”错误,但如果我将它们更改为“ConverterParameter=0”,则应用程序会运行.我基于How to bind RadioButtons to an enum?
  2. 默认国家/地区列表最初显示在 ComboBox 中,但默认国家/地区不显示,而是空白。
  3. 单击 RadioButton 对列表没有影响。

显然我做错了什么,但我不知道是什么。你能帮忙吗?

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# 代码背后(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;
    }
}

【问题讨论】:

    标签: c# wpf combobox radio-button


    【解决方案1】:

    我会为每个单选按钮设置一个 bool 属性,而不是使用转换器。然后检查您的过滤器。

    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;
    }
    

    【讨论】:

    • 我添加了您的代码并将CountryView.Filter = o =&gt; selectedContinent == null || ((Country)o).Continent == selectedContinent.Model; 更改为CountryView.Filter += CountryFilter; 在XAML 中我将IsChecked... 更改为IsChecked="{Binding Path=Africa}",但ComboBox 仍未过滤。
    • 您需要在属性设置器中刷新视图。我改变了我的例子。
    • 感谢您的更新。 ComboBox 现已更新并显示正确的国家/地区。但是,如果我选择一个国家然后单击 RadioButton 我会收到错误消息:Object reference not set to an instance of an object CountryView.Refresh()Error: 40 : BindingExpression path error: 'DisplayName' property not found on 'object' ''String' (HashCode=1228963566)'. BindingExpression:Path=DisplayName; DataItem='String' (HashCode=1228963566); target element is 'DummyObject' (Name=''); target property is 'Content' (type 'Object')
    猜你喜欢
    • 2020-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多