Привязка RibbonComboBox к отфильтрованной ObservableCollection вызывает ошибки - PullRequest
0 голосов
/ 24 сентября 2019

Используя C #, я пытаюсь отфильтровать список RibbonComboBox с помощью RibbonRadioButtons, но не могу устранить ошибку, которую я продолжаю получать.

Список стран находится в ObservableCollection, который я фильтрую, используя ListCollectionView.С помощью другого пользователя ( C # WPF-фильтр ComboBox на основе RadioButtons ) у меня теперь он частично работает, но если я нажимаю на переключатель, список в ComboBox обновляется, но в ComboBox ничего не отображается;Я ожидал, что будет отображен первый элемент в списке.Если я выбираю страну, а затем щелкаю другой континент в RadioButton, я получаю сообщение об ошибке, показанное ниже в строке «public bool Africa {... CountryView.Refresh () }» или в зависимости от того, на какую кнопку я нажал. [Код обновлен 25 сентября для отражения комментариев.]

Ошибки RibbonComboBox

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'

Когда я изменил RibbonComboBox на ComboBox в 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 # (DataContext):

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 Ответ

0 голосов
/ 26 сентября 2019

Я изменил ваш класс, чтобы решить ваши проблемы.Изменения в коде:

  1. Вместо CountryView = new ListCollectionView(countries) do CountryView = (ListCollectionView)CollectionViewSource.GetDefaultView(countries)
  2. При каждом обновлении вашего списка, т.е. при проверке CheckBox, установите SelectedItemваш ComboBox т.е. 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));
    }
    
...