首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DataBinding wpf KeyedCollection

DataBinding wpf KeyedCollection
EN

Stack Overflow用户
提问于 2009-06-03 10:06:27
回答 5查看 1.4K关注 0票数 1

我是WPF数据绑定的初学者,我刚刚发现了一种令人困惑的行为。也许有人能帮我:

我的xaml代码将一个列表框绑定到一个列表:

代码语言:javascript
复制
<ListBox ItemsSource="{Binding Path=Axes}"  SelectedItem="{Binding Path = SelectedAxis}" DisplayMemberPath = "Name" Name="listboxAxes"/>

如果绑定到的实际项是一个列表,那么一切都会按预期进行。

但是,当我切换到KeyedCollection时,出现了一个更新问题。对NotifyPropertychanged("Axes")的调用不会作为一个整体更新ListBox。

对此有什么想法吗?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2009-06-09 20:19:24

如果正在收集的轴不是具有自己的Name属性的类,那么DisplayMemberPath=的“Name”属性可能会导致您看不到任何东西。

不过,将KeyedCollection用作ItemsSource是完全可以的。ItemsSource属性是ItemsControl.ItemsSource属性。它只要求它绑定到的任何东西都实现IEnumerable。

KeyedCollection实现了IEnumerable,因为它实现了集合。

下面是一个使用KeyedCollection的简短示例:

代码语言:javascript
复制
<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>

我们的窗口和KeyedCollection的代码如下:

代码语言:javascript
复制
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什么也做不了。

我们再添加两个按钮来演示这一点:

代码语言:javascript
复制
<Button DockPanel.Dock="Top"
        Content="Add Zebra"
        Click="AddZebraClick" />
<Button DockPanel.Dock="Top"
        Content="Add YoYo"
        Click="AddYoYoClick" />

还有汉德尔一家:

代码语言:javascript
复制
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时,必须实际更改该属性。在这种情况下,情况并非如此。我们已经修改了它的items,但是Examples集合仍然是同一个集合。为了解决这个问题,我们可以像在第一部分中一样循环集合,或者如果我们有权访问UI,我们可以调用:

代码语言:javascript
复制
uiListBox.Items.Refresh();

我们也可以循环DataSource,我们可以循环列表框的ItemsSource,或者我们可以清除并重新分配绑定,但是仅仅调用UpdateTarget()并不能做到这一点。

票数 4
EN

Stack Overflow用户

发布于 2009-06-03 11:01:25

尝试调用listboxAxes.Items.Refresh()。这有时会有帮助。

票数 2
EN

Stack Overflow用户

发布于 2009-06-09 11:36:24

KeyedCollection既不实现INotifyCollectionChanged也不实现INotifyPropertyChanged。要让绑定自动更新自身,请使用实现这些接口的集合(例如ObservableCollection)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/943952

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档