WPF ComboBox Не обновляется в случае события, измененного - PullRequest
0 голосов
/ 31 января 2019

У меня есть пользовательский комбинированный список в моем приложении WPF, и поле со списком не обновляется, когда мой источник элемента обновляется после первоначального запуска.ItemsSource - это пользовательский observableDictionary.Я реализовал INotifyPropertyChanged в своих свойствах с моим observableDictionary, но он не будет обновляться.Я просматривал каждое событие с измененным свойством WPF, не работающее с переполнением стека, и мне нужна помощь.

Код пользовательского комбинированного списка:

<controls:MultiSelectComboBox Width="100" Height="30" Padding="0 10 0 0" Grid.Row="0" Grid.Column="1"
    ItemsSource="{Binding Mode=TwoWay,             
                  UpdateSourceTrigger=PropertyChanged,                                                    
                  ValidatesOnDataErrors=True, 
                  Path=DataContext.OptionTeamMembersDictionary, 
                  BindsDirectlyToSource=True,                                                    
                  RelativeSource={RelativeSource AncestorType={x:Type UserControl},Mode=FindAncestor}}"
    SelectedItems="{Binding SelectedOptionTeamMembersDictionary, Mode=TwoWay}"
    x:Name="TeamMemberDisplay" 
    ToolTip="{Binding Path=Text, RelativeSource={RelativeSource Self}}"/>

Свойства и частные переменные:

private ObservableDictionary<string, object> _optionTeamMembersDictionary;
private ObservableDictionary<string, object> _selectedOptionTeamMembersDictionary;


public ObservableDictionary<string, object> OptionTeamMembersDictionary
{
    get
    {
        return _optionTeamMembersDictionary;
    }
    set
    {
        _optionTeamMembersDictionary = value;
        OnPropertyChanged("OptionTeamMembersDictionary");
    }
}

public ObservableDictionary<string, object> SelectedOptionTeamMembersDictionary
{
    get
    {
        return _selectedOptionTeamMembersDictionary;
    }
    set
    {
        _selectedOptionTeamMembersDictionary = value;
        OnPropertyChanged("SelectedOptionTeamMembersDictionary");
    }
}

Я использую кнопку для запуска извлечения базы данных, которое приводит каждую строку в объект, а затем заполняет optionTeamMemberDictionary, когда он возвращает более одной строки данных.

Все вышеперечисленное работает, когдаданные загружаются в мой конструктор, но когда они загружаются после запуска, мои комбинированные списки не отображают новые данные в коллекции.

РЕДАКТИРОВАТЬ: код для используемого настраиваемого комбинированного списка: https://www.codeproject.com/Articles/563862/Multi-Select-ComboBox-in-WPF - это URL-адрес этогопришли из.Некоторые изменения были внесены для реализации obserableDirctionary вместо обычного словаря

public partial class MultiSelectComboBox : UserControl
{
    private ObservableCollection<Node> _nodeList;
    public MultiSelectComboBox()
    {
        InitializeComponent();
        _nodeList = new ObservableCollection<Node>();
    }

    #region Dependency Properties

    public static readonly DependencyProperty ItemsSourceProperty =
         DependencyProperty.Register("ItemsSource", typeof(ObservableDictionary<string, object>), typeof(MultiSelectComboBox), new FrameworkPropertyMetadata(null,
    new PropertyChangedCallback(MultiSelectComboBox.OnItemsSourceChanged)));

    public static readonly DependencyProperty SelectedItemsProperty =
     DependencyProperty.Register("SelectedItems", typeof(ObservableDictionary<string, object>), typeof(MultiSelectComboBox), new FrameworkPropertyMetadata(null,
 new PropertyChangedCallback(MultiSelectComboBox.OnSelectedItemsChanged)));

    public static readonly DependencyProperty TextProperty =
       DependencyProperty.Register("Text", typeof(string), typeof(MultiSelectComboBox), new UIPropertyMetadata(string.Empty));

    public static readonly DependencyProperty DefaultTextProperty =
        DependencyProperty.Register("DefaultText", typeof(string), typeof(MultiSelectComboBox), new UIPropertyMetadata(string.Empty));

    public ObservableDictionary<string, object> ItemsSource
    {
        get { return (ObservableDictionary<string, object>)GetValue(ItemsSourceProperty); }
        set
        {
            SetValue(ItemsSourceProperty, value);
        }
    }

    public ObservableDictionary<string, object> SelectedItems
    {
        get { return (ObservableDictionary<string, object>)GetValue(SelectedItemsProperty); }
        set
        {
            SetValue(SelectedItemsProperty, value);
        }
    }

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    public string DefaultText
    {
        get { return (string)GetValue(DefaultTextProperty); }
        set { SetValue(DefaultTextProperty, value); }
    }
    #endregion

    #region Events
    private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        MultiSelectComboBox control = (MultiSelectComboBox)d;
        control.DisplayInControl();
    }

    private static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        MultiSelectComboBox control = (MultiSelectComboBox)d;
        control.SelectNodes();
        control.SetText();
    }

    private void CheckBox_Click(object sender, RoutedEventArgs e)
    {
        CheckBox clickedBox = (CheckBox)sender;

        if (clickedBox.Content == "All")
        {
            if (clickedBox.IsChecked.Value)
            {
                foreach (Node node in _nodeList)
                {
                    node.IsSelected = true;
                }
            }
            else
            {
                foreach (Node node in _nodeList)
                {
                    node.IsSelected = false;
                }
            }
        }
        else
        {
            int _selectedCount = 0;
            foreach (Node s in _nodeList)
            {
                if (s.IsSelected && s.Title != "All")
                    _selectedCount++;
            }
            if (_selectedCount == _nodeList.Count - 1)
                _nodeList.FirstOrDefault(i => i.Title == "All").IsSelected = true;
            else
                _nodeList.FirstOrDefault(i => i.Title == "All").IsSelected = false;
        }
        SetSelectedItems();
        SetText();
    }
    #endregion

    #region Methods
    private void SelectNodes()
    {
        foreach (KeyValuePair<string, object> keyValue in SelectedItems)
        {
            Node node = _nodeList.FirstOrDefault(i => i.Title == keyValue.Key);
            if (node != null)
                node.IsSelected = true;
        }
    }

    private void SetSelectedItems()
    {
        if (SelectedItems == null)
            SelectedItems = new ObservableDictionary<string, object>();
        SelectedItems.Clear();
        foreach (Node node in _nodeList)
        {
            if (node.IsSelected && node.Title != "All")
            {
                if (this.ItemsSource.Count > 0)
                    SelectedItems.Add(node.Title, this.ItemsSource[node.Title]);
            }
        }
    }

    private void DisplayInControl()
    {
        _nodeList.Clear();
        if (this.ItemsSource.Count > 0)
            _nodeList.Add(new Node("All"));
        foreach (KeyValuePair<string, object> keyValue in this.ItemsSource)
        {
            Node node = new Node(keyValue.Key);
            _nodeList.Add(node);
        }
        MultiSelectCombo.ItemsSource = _nodeList;
    }

    private void SetText()
    {
        if (this.SelectedItems != null)
        {
            StringBuilder displayText = new StringBuilder();
            foreach (Node s in _nodeList)
            {
                if (s.IsSelected == true && s.Title == "All")
                {
                    displayText = new StringBuilder();
                    displayText.Append("All");
                    break;
                }
                else if (s.IsSelected == true && s.Title != "All")
                {
                    displayText.Append(s.Title);
                    displayText.Append(',');
                }
            }
            this.Text = displayText.ToString().TrimEnd(new char[] { ',' });
        }
        // set DefaultText if nothing else selected
        if (string.IsNullOrEmpty(this.Text))
        {
            this.Text = this.DefaultText;
        }
    }


    #endregion
}

public class Node : INotifyPropertyChanged
{

    private string _title;
    private bool _isSelected;
    #region ctor
    public Node(string title)
    {
        Title = title;
    }
    #endregion

    #region Properties
    public string Title
    {
        get
        {
            return _title;
        }
        set
        {
            _title = value;
            NotifyPropertyChanged("Title");
        }
    }
    public bool IsSelected
    {
        get
        {
            return _isSelected;
        }
        set
        {
            _isSelected = value;
            NotifyPropertyChanged("IsSelected");
        }
    }
    #endregion

    public event PropertyChangedEventHandler PropertyChanged;
    public void NotifyPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

1 Ответ

0 голосов
/ 03 февраля 2019

После долгих ошибок я смог найти ответ на этот вопрос.onItemsSourceChanged не запускался после того, как был создан элемент управления, поэтому он не получал обновления, сделанные после первоначального запуска приложения.Я отредактировал функцию OnItemsSourceChanged на MultiFunctionComboBox так, чтобы она запускалась при изменении события и теперь работала, как и ожидалось.

private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            MultiSelectComboBox control = (MultiSelectComboBox)d;

            var action = new NotifyCollectionChangedEventHandler(
                (o, args) =>
                {
                    MultiSelectComboBox c = (MultiSelectComboBox)d;

                    c?.DisplayInControl();
                });

            if (e.OldValue != null)
            {
                var sourceCollection = (ObservableDictionary<string, object>)e.OldValue;
                sourceCollection.CollectionChanged -= action;
            }

            if (e.NewValue != null)
            {
                var sourceCollection = (ObservableDictionary<string, object>)e.NewValue;
                sourceCollection.CollectionChanged += action;
            }

            control.DisplayInControl();
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...