DataBinding wpf KeyedCollection

Я новичок в WPF Databinding, и я просто нашел сбивающее с толку поведение. Может быть, кто-то может мне помочь:

Мой код xaml связывает список со списком:

<ListBox ItemsSource="{Binding Path=Axes}"  SelectedItem="{Binding Path = SelectedAxis}" DisplayMemberPath = "Name" Name="listboxAxes"/>

Если фактический элемент, связанный с ним, является списком, все работает так, как ожидалось.

Но когда я перехожу к <Grid> <DockPanel x: Name = "QuickListButtonsStackPanel" > <Button DockPanel . Dock = "Top" Content = "Load Animals" Нажмите = "AnimalButtonClick" /> <Button DockPanel . Dock = "Top" Content = "Load Objects" Нажмите = "ObjectButtonClick" /> <TextBlock DockPanel . Dock = "Bottom" Фон = "Azure" Текст = "{Binding SelectedExample}" /> <ListBox x: Name = "uiListBox" ItemsSource = "{Примеры привязки }" SelectedItem = "{Binding SelectedExample}" /> </ DockPanel> </ Grid> возникает проблема с обновлением. Вызовы NotifyPropertychanged («Оси») НЕ обновляют ListBox в целом.

Есть идеи об этом?

c#,wpf,data-binding,xaml,

1

Ответов: 5


4 принят
+50

Если любые осей собирают не класс с собственным свойством Name, свойство DisplayMemberPath = «Name» может заставлять вас ничего не видеть.

Однако использование KeyedCollection в качестве элемента Items прекрасно. Свойством ItemsSource является свойство ItemsControl.ItemsSource . И это просто требует, чтобы все, что связано с IEnumerable.

KeyedCollection реализует IEnumerable, поскольку он реализует Collection.

Ниже приведен короткий пример с помощью KeyedCollection:

public partial class Window1 : Window, INotifyPropertyChanged
{
    public Window1()
    {
        InitializeComponent();
        this.DataContext = this;
    }

    public KeyedCollection<char, string> Examples
    {
        get;
        set;
    }

    private string mySelectedExample;
    public string SelectedExample
    {
        get
        { return this.mySelectedExample; }
        set
        {
            this.mySelectedExample = value;
            this.NotifyPropertyChanged("SelectedExample");
        }
    }

    private void AnimalButtonClick(object sender, RoutedEventArgs e)
    {
        Examples = new AlphabetExampleCollection();
        Examples.Add("Ardvark");
        Examples.Add("Bat");
        Examples.Add("Cat");
        Examples.Add("Dingo");
        Examples.Add("Emu");

        NotifyPropertyChanged("Examples");
    }

    private void ObjectButtonClick(object sender, RoutedEventArgs e)
    {
        Examples = new AlphabetExampleCollection();
        Examples.Add("Apple");
        Examples.Add("Ball");
        Examples.Add("Chair");
        Examples.Add("Desk");
        Examples.Add("Eee PC");

        NotifyPropertyChanged("Examples");
    }



    #region INotifyPropertyChanged Members

    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion
}

public class AlphabetExampleCollection : KeyedCollection<char, string>
{
    public AlphabetExampleCollection() : base() { }

    protected override char GetKeyForItem(string item)
    {
        return Char.ToUpper(item[0]);
    }
}

И код для нашего Window & KeyedCollection:

<Button DockPanel.Dock="Top"
        Content="Add Zebra"
        Click="AddZebraClick" />
<Button DockPanel.Dock="Top"
        Content="Add YoYo"
        Click="AddYoYoClick" />

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

Давайте добавим еще две кнопки, чтобы продемонстрировать это:

private void AddZebraClick(object sender, RoutedEventArgs e)
{
    Examples.Add("Zebra");
    NotifyPropertyChanged("Examples");
}

private void AddYoYoClick(object sender, RoutedEventArgs e)
{
    Examples.Add("YoYo");
    NotifyPropertyChanged("Examples");
}

И хандлеров:

uiListBox.Items.Refresh();

Оба эти, как и не будут работать . Когда вы вызываете NotifyPropertyChanged, свойство должно быть действительно изменено. И в этом случае это не так. Мы изменили его элементы, но коллекция примеров по-прежнему остается той же коллекцией. Чтобы исправить это, мы могли бы цитировать коллекцию, как мы это делали в первой части, или если у нас есть доступ к пользовательскому интерфейсу, мы могли бы позвонить:

listboxAxes.Items.Refresh()

Мы также могли бы циклировать DataSource, мы могли бы циклически использовать ItemsSource ListBox, иначе мы могли бы очистить и повторно назначить привязку, но просто вызов UpdateTarget () не будет делать этого.


2

Попробуйте позвонить KeyedCollection. Иногда это помогает.


1

KeyedCollectionне реализует ни и INotifyCollectionChangedне INotifyPropertyChanged. Чтобы привязка автоматически обновлялась, используйте коллекцию, которая реализует эти интерфейсы ( ObservableCollectionнапример).



0

Выделите ваше свойство как свойство типа IList и привяжите ItemSource к этому свойству:

public IList MyIListKeyedCollection { get { return myKeyedCollection; } }

и выполняйте вызов NotifyPropertyChanged («MyIListKeyedCollection») при каждом изменении myKeyedCollection. Я думаю, что это должно работать ...

C #, WPF, связывания данных, XAML,
Похожие вопросы