Cuadro de lista vinculado a ObservableCollection (en VB.NET y Silverlight)

Sorry if this is a duplicate question. There are quite a few questions around this topic, but I can't seem to get it figured out. I'm trying to bind a listbox to an ObservableCollection and keep the listbox updated when items are added to the collection.

I have a class called CollectionOfBlogs:

Public Class CollectionOfBlogs
    Implements INotifyPropertyChanged

    Public Event PropertyChanged As PropertyChangedEventHandler _
    Implements INotifyPropertyChanged.PropertyChanged

    Public Sub New(ByVal name As String)
        Me.FullName = name
    End Sub

    Private _FullName As String
    Public Property FullName() As String
        Get
            Return _FullName
        End Get
        Set(ByVal value As String)
            _FullName = value
            NotifyPropertyChanged("FullName")
        End Set
    End Property

    Public Sub NotifyPropertyChanged(ByVal propertyName As String)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
    End Sub

End Class

Then another class where I setup the ObservableCollection of CollectionOfBlogs (above) and a sub to add items to the collection:

Public Class ITRSBlogs

    Public blogNamesList As New ObservableCollection(Of CollectionOfBlogs)

    Public Sub addBlog(ByVal FullName as String)
        blogNamesList.Add(New CollectionOfBlogs(FullName))
    End Sub

End Class

I bind the listbox to the blogNamesList collection in the ITRSBlogs Class (above) from my main page loaded event:

Dim blogClass As New ITRSBlogs

Me.BloggingMenuListBox.ItemsSource = blogClass.blogNamesList

Here is the XAML of my listbox. It's bound in the codebehind, not in the XAML (just thought I should mention that).

<ListBox Name="BloggingMenuListBox"/>

Before binding the collection to the listbox, I load the collection with items from the database, and they show up in the listbox just fine. These 2 subs below are actually in the ITRSBlogs Class as well, and I call FillBlogLists from my pages loaded event.

Public Sub FillBlogLists()
    Dim query = theContext.GetBlogsOrderedByNameQuery
    theContext.Load(query, AddressOf OnBlogsLoaded, Nothing)
End Sub

Private Sub OnBlogsLoaded(ByVal lo As LoadOperation(Of Blog))
    blogList.Clear()
    For Each s In lo.AllEntities
        blogList.Add(CType(s, Blog))
    Next
    For Each item In blogList
        blogNamesList.Add(New CollectionOfBlogs(item.FullName))
    Next
End Sub

Beyond this, I have a simple textbox and button on a page. When a name is entered into the textbox, and the button is clicked, I call the addBlog(passing in name from textbox) sub routine in the ITRSBlogs Class (back up the page a bit) to add the item to the collection.

Problem is, when I add an item to the collection, the listbox is not updated. I'm new to Observable Collections (and many other things : ), so maybe I'm just really off here. Can anyone tell me what I'm doing wrong?

preguntado el 09 de enero de 11 a las 05:01

1 Respuestas

The code you posted looks fine to me. I replicated your code (in C#, but I tried to keep it as close to your code as possible) and it just worked. The only code you didn't post is the event handler of the Add button. Did you check that it is actually called and that a new item is added to the collection?

Anyway here is my code, maybe you can spot where the difference is between this and your version:

CollectionOfBlogs.cs:

public class CollectionOfBlogs : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private string _FullName;
    public string FullName
    {
        get
        {
            return this._FullName;
        }
        set
        {
            if (this._FullName != value)
            {
                this._FullName = value;
                this.OnPropertyChanged("FullName");
            }
        }
    }

    public CollectionOfBlogs(string name)
    {
        this._FullName = name;
    }

    public virtual void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public override string ToString()
    {
        return this._FullName;
    }

}

ITRSBlogs.cs:

public class ITRSBlogs
{
    public ObservableCollection<CollectionOfBlogs> blogNamesList = new ObservableCollection<CollectionOfBlogs>();

    public void AddBlog(string fullName)
    {
        this.blogNamesList.Add(new CollectionOfBlogs(fullName));
    }

    public void FillBlogList()
    {
        this.blogNamesList.Clear();
        this.AddBlog("First blog");
        this.AddBlog("Another blog");
    }
}

MainWindow.xaml:

<Window x:Class="ObservableRefreshDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
  <Grid>
    <ListBox Name="BloggingMenuListBox"/>
    <Button Content="Add" Height="23" HorizontalAlignment="Left" Margin="154,276,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
    <TextBox Height="23" HorizontalAlignment="Left" Margin="12,276,0,0" Name="txtName" VerticalAlignment="Top" Width="120" />
  </Grid>
</Window>

MainWindow.xaml.cs:

public partial class MainWindow : Window
{

    private ITRSBlogs blogClass = new ITRSBlogs();

    public MainWindow()
    {
        InitializeComponent();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        this.blogClass.FillBlogList();
        this.BloggingMenuListBox.ItemsSource = this.blogClass.blogNamesList;
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        this.blogClass.AddBlog(this.txtName.Text);
    }
}

Respondido el 09 de enero de 11 a las 10:01

Thanks TomBot, I think I understand what's wrong, but I don't know how to fix it. I did leave out some important points I see. On my MainPage I have a menu with lots of choices, one of those choices is to add a new blog. When you click that button, it loads a different page where the actual textbox and save button are. So, this page also has a Dim blogClass as New ITRSBlogs, and it does call the addblog method and add the name in the textbox to the collection. However I dont have a good understanding of how the listbox bound to the collection back on the mainpage get's updated. - Chris Phelps

In other words, I think I've got multiple copies of the collection going, and I'm not sure how that all works. How do I ensure that I'm looking at the same collection on both pages? - Chris Phelps

You definitely have to make sure that you only have one collection. The simplest solution would be that the collection is in the MainPage, and when you open the AddDialog, you give a reference to the collection to it. Something like AddDialog dlg = new AddDialog(); dlg.Collction = this.Collection; dlg.ShowDialog(); - TomBot

Thank you TomBot, you got me looking in the right direction. I found a good example of this here: Dave Corun's Blog -davecorun.com/blog/2010/08/01/… - Chris Phelps

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.