Связывание данных wpf KeyedCollection - PullRequest
1 голос
/ 03 июня 2009

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

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

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

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

Но когда я перехожу на KeyedCollection, возникает проблема обновления. Вызовы NotifyPropertychanged («Axes») НЕ обновляют ListBox в целом.

Есть идеи по этому поводу?

Ответы [ 5 ]

4 голосов
/ 10 июня 2009

Если то, что собирает Axes, не является классом со своим собственным свойством Name, то свойство DisplayMemberPath = "Name" может привести к тому, что вы ничего не увидите.

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

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

Вот небольшой пример использования KeyedCollection:

<Grid>
    <DockPanel x:Name="QuickListButtonsStackPanel">
        <Button DockPanel.Dock="Top"
                Content="Load Animals"
                Click="AnimalButtonClick" />
        <Button DockPanel.Dock="Top"
                Content="Load Objects"
                Click="ObjectButtonClick" />

        <TextBlock DockPanel.Dock="Bottom"
                   Background="Azure"
                   Text="{Binding SelectedExample}" />

        <ListBox x:Name="uiListBox"
                 ItemsSource="{Binding Examples}"
                 SelectedItem="{Binding SelectedExample}" />

    </DockPanel>
</Grid>

И код для нашей Window & 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]);
    }
}

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

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

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

И Хандлерс:

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

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

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

uiListBox.Items.Refresh();

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

2 голосов
/ 03 июня 2009

Попробуйте позвонить listboxAxes.Items.Refresh(). Это иногда помогает.

1 голос
/ 09 июня 2009

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

0 голосов
/ 16 июня 2009

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

public IList MyIListKeyedCollection { get { return myKeyedCollection; } }

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

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