将功能区组合框绑定到导致错误的筛选可观察集合



使用C# 我尝试使用 RibbonRadioButton 过滤 RibbonComboBox 列表,但我无法解决我一直收到的错误。

国家/地区列表位于我使用 ListCollectionView 过滤的可观察集合中。在另一个用户(基于 RadioButton 的 C# WPF 筛选器组合框(的帮助下,我现在让它部分工作,但是如果我单击单选按钮,组合框中的列表会更新,但组合框中没有显示任何内容;我希望显示列表中的第一项。如果我选择一个国家,然后从单选按钮单击另一个大陆,我收到下面显示的错误"公共布尔非洲{...CountryView.Refresh((}'或我点击的任何按钮。[代码于 9 月 25 日更新以反映评论。

功能区组合框错误

Object reference not set to an instance of an object.
In VS Output window:
Error: 40 : BindingExpression path error: 'DisplayName' property not found on 'object'

当我将 XAML 中的功能区组合框更改为组合框时,如下所示,尽管它生成了另一个错误,但它似乎确实可以正常工作。但是,我更喜欢使用RibbonComboBox,但不确定如何解决问题。您可以提供的任何帮助以使其正常工作将不胜感激。

XAML

<Grid>
<DockPanel>
<r:Ribbon DockPanel.Dock="Top" x:Name="Ribbon">
<r:RibbonGroup Header="Continent" Width="260">
<!--<ComboBox x:Name="CountryList" Width="100" ItemsSource="{Binding CountryView}" SelectedItem="{Binding SelectedCountry}" DisplayMemberPath="DisplayName"/>-->
<r:RibbonComboBox x:Name="CountryList" Height="Auto" SelectionBoxWidth="230" VerticalAlignment="Center">
<r:RibbonGallery x:Name="cbSelectedCountry" SelectedValue="{Binding SelectedCountry, Mode=TwoWay}" SelectedValuePath="DisplayName" >
<r:RibbonGalleryCategory x:Name="cbCountryList" ItemsSource="{Binding CountryView}" DisplayMemberPath="DisplayName" />
</r:RibbonGallery>
</r:RibbonComboBox>
<WrapPanel>
<r:RibbonRadioButton x:Name="All" Label="All" GroupName="ContinentGroup" Height="Auto" Width="Auto" HorizontalAlignment="Left" IsChecked="{Binding Path=All}">
</r:RibbonRadioButton>
<r:RibbonRadioButton x:Name="Africa" Label="Africa" GroupName="ContinentGroup" Height="Auto" Width="Auto" HorizontalAlignment="Left" IsChecked="{Binding Path=Africa}">
</r:RibbonRadioButton>
<r:RibbonRadioButton x:Name="America" Label="America" GroupName="ContinentGroup" Height="Auto" Width="Auto" HorizontalAlignment="Left" IsChecked="{Binding Path=America}">
</r:RibbonRadioButton>
</WrapPanel>
</r:RibbonGroup>
</r:Ribbon>
</DockPanel>
</Grid>

C# 代码隐藏 (数据上下文(:

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows.Data;
public class MySettings : INotifyPropertyChanged
{
private readonly ObservableCollection<Country> countries;
private ContinentViewModel selectedContinent;
private static string selectedCountry;
private int selectedRadioGroup;
private ObservableCollection<ContinentViewModel> continents;
private ListCollectionView countryView;
public event PropertyChangedEventHandler PropertyChanged;
private bool _All;
private bool _Africa;
private bool _America;
public bool All { get => _All; set { _All = value; CountryView.Refresh(); SelectedCountry = countries[0].ToString(); } }
public bool Africa { get => _Africa; set { _Africa = value; CountryView.Refresh(); SelectedCountry = countries[0].ToString(); } }
public bool America { get => _America; set { _America = value; CountryView.Refresh(); SelectedCountry = countries[0].ToString(); } }
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.Africa, DisplayName = "Chad" },
new Country() { Continent = Continent.Africa, DisplayName = "Ghana" },
new Country() { Continent = Continent.America, DisplayName = "Canada" },
new Country() { Continent = Continent.America, DisplayName = "Greenland" },
new Country() { Continent = Continent.America, DisplayName = "Haiti" }
});
CountryView = (ListCollectionView)CollectionViewSource.GetDefaultView(countries);
CountryView.Filter += CountryFilter;
Continents = new ObservableCollection<ContinentViewModel>(Enum.GetValues(typeof(Continent)).Cast<Continent>().Select(c => new ContinentViewModel { Model = c }));
}
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 (America) return country.Continent == Continent.America;
return true;
}
public ObservableCollection<ContinentViewModel> Continents
{
get { return continents; }
set
{
continents = value;
}
}
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,
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;
}
}
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}

我已经修改了您的类来解决您的问题。代码中的更改是:

  1. 而不是CountryView = new ListCollectionView(countries)CountryView = (ListCollectionView)CollectionViewSource.GetDefaultView(countries)
  2. 在每次刷新列表时,即检查CheckBox时,设置组合框的SelectedItem,即在您的情况下SelectedCountry如下:SelectedCountry = _All ? countries.FirstOrDefault().DisplayName : SelectedCountry;SelectedCountry = _Africa ? countries.Where(_ => _.Continent == Continent.Africa).FirstOrDefault().DisplayName : SelectedCountry;SelectedCountry = _America ? countries.Where(_ => _.Continent == Continent.America).FirstOrDefault().DisplayName : SelectedCountry;
  3. 调用所有属性的OnPropertyChanged

    private readonly ObservableCollection<Country> countries;
    private ContinentViewModel selectedContinent;
    private static string selectedCountry;
    private int selectedRadioGroup;
    private ObservableCollection<ContinentViewModel> continents;
    private ListCollectionView countryView;
    public event PropertyChangedEventHandler PropertyChanged;
    private bool _All;
    private bool _Africa;
    private bool _America;
    public bool All
    {
    get
    {
    return _All;
    }
    set
    {
    _All = value;
    CountryView.Refresh();
    SelectedCountry = _All ? countries.FirstOrDefault().DisplayName : SelectedCountry;
    OnPropertyChanged("All");
    }
    }
    public bool Africa
    {
    get
    {
    return _Africa;
    }
    set
    {
    _Africa = value;
    CountryView.Refresh();
    SelectedCountry = _Africa ? countries.Where(_ => _.Continent == Continent.Africa).FirstOrDefault().DisplayName : SelectedCountry;
    OnPropertyChanged("Africa");
    }
    }
    public bool America
    {
    get
    {
    return _America;
    }
    set
    {
    _America = value;
    CountryView.Refresh();
    SelectedCountry = _America ? countries.Where(_ => _.Continent == Continent.America).FirstOrDefault().DisplayName : SelectedCountry;
    OnPropertyChanged("America");
    }
    }
    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.Africa, DisplayName = "Chad" },
    new Country() { Continent = Continent.Africa, DisplayName = "Ghana" },
    new Country() { Continent = Continent.America, DisplayName = "Canada" },
    new Country() { Continent = Continent.America, DisplayName = "Greenland" },
    new Country() { Continent = Continent.America, DisplayName = "Haiti" }
    });
    CountryView = (ListCollectionView)CollectionViewSource.GetDefaultView(countries);
    CountryView.Filter += CountryFilter;
    Continents = new ObservableCollection<ContinentViewModel>(Enum.GetValues(typeof(Continent)).Cast<Continent>().Select(c => new ContinentViewModel { Model = c }));
    }
    private bool CountryFilter(object obj)
    {
    var country = obj as Country;
    if (country == null) return false;
    if (All && !Africa && !America) return true;
    else if (!All && Africa && !America) return country.Continent == Continent.Africa;
    else if (!All && !Africa && America) return country.Continent == Continent.America;
    return true;
    }
    public ObservableCollection<ContinentViewModel> Continents
    {
    get { return continents; }
    set
    {
    continents = value;
    OnPropertyChanged("Continents");
    }
    }
    public ListCollectionView CountryView
    {
    get { return countryView; }
    set
    {
    countryView = value;
    OnPropertyChanged("CountryView");
    }
    }
    public class Country
    {
    public string DisplayName { get; set; }
    public Continent Continent { get; set; }
    }
    public enum Continent
    {
    All,
    Africa,
    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;
    OnPropertyChanged("SelectedRadioGroup");
    }
    }
    public string SelectedCountry
    {
    get { return selectedCountry; }
    set
    {
    if (selectedCountry == value) return;
    selectedCountry = value;
    OnPropertyChanged("SelectedCountry");
    }
    }
    protected virtual void OnPropertyChanged(string propertyName)
    {
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    

最新更新