rbb
rbb

Reputation: 59

Binding ObservableCollection to ListView

I've been following this tutorial to try to work an understanding of XML, WPF, and C# (coming out from Fortran). I've gotten the functionality working (thanks to the tutorial), but I'm having troubles modifying it to work with WPF instead of WinForms.

Essentially, when I click the "Get RSS" button, the following is happening:

RssManager reader = new RSSManager();
ObservableCollection<Rss.Items> _list = new ObservableCollection<Rss.Items>();
reader.Url = txtFeed.Text;
reader.GetFeed();
_list = (ObservableCollection<Rss.Items>)reader.RssItems;

The listview just sits blank. It's code is like the following. Also, trying this with a listbox results in the name of the class being populated for each item in the list instead of my data:

<ListView ItemsSource="_rssItems">
    <ListView.View>
        <GridView>
            <GridViewColumn DisplayMemberBinding="{Binding Title}"/>
        </GridView>
    </ListView.View>
</ListView>

Would it be possible to do something like (again, forgive me for my ignorance, here):

_list.Add( new Rss.Items());

The list (_list) contains all of the information that I need, I just want to figure out how to properly bind it (or add it) to the ListView.

Upvotes: 1

Views: 3629

Answers (2)

Brian S
Brian S

Reputation: 5785

As Lee suggests in his comment, the binding for the ItemsSource property of the ListView does not appear to be correct. There are multiple ways to approach this, depending on how your project is designed/structured.

In order to DataBind, the ListView will need some kind of DataContext which (as the name implies) is kind of the Context for the Binding. If you are using MVVM, then most likely, the DataContext of your entire Window/Control would be a ViewModel. In that case, you bind to a property of the ViewModel like this:

<ListView ItemsSource="{Binding RssItems}">...</ListView>

This assumes you have a ViewModel with a public RssItems property (which is some kind of List/Enumerable) and the ViewModel is DataContext.

If you are not using MVVM, there are a lot of ways to assign the ItemsSource both with DataBinding and without. The easiest way I can suggest, if you're not fully comfortable with DataBinding, would be to manually assign the ItemsSource, like this:

Xaml:

<ListView x:Name="MyRssList">...</ListView>

Code Behind (somewhere after the UI has Loaded and after you've created/populated _list):

MyRssList.ItemsSource = _list;

This doesn't use DataBinding, but it will get the job done. If you want to start out with DataBinding, you could do the following:

XAML:

<ListView x:Name="MyRssList" ItemsSource="{Binding}>...</ListView>

Code Behind:

MyRssList.DataContext = _list;

This will assign the List as the DataContext of the ListView, then DataBind the ItemsSource property to the DataContext.

Overall, You're on the right track. I'd recommend some reading on DataBinding and MVVM. MVVM is a very good way to leverage the powerful DataBinding capabilities of WPF, and a strong understanding of DataBinding is extremely valuable in designing and building great WPF apps.

Hope this helps. Good luck!

Upvotes: 0

Neil
Neil

Reputation: 1633

It looks like you are a bit lost.

Ultimately you want to bind your view(WPF form) to a View-Model and your View-Model to a model (the RSSManager).

For now lets bind the view directly to the model.

In your constructor you make a new instance of the model and you assign it to the data context.

This model is going to live as long as the form -

    public MainWindow()
    {
        InitializeComponent();
        _model = new RssManager();
        DataContext = _model;

    }

Then in your XAML you bind the item source to your collection property :

       <ListView ItemsSource="{Binding Path=RssItems}">
            <ListView.View>
                <GridView>
                    <GridViewColumn DisplayMemberBinding="{Binding Title}"/>
                </GridView>
            </ListView.View>
        </ListView>

Note that in "Path=RssItems" is relative to whatever you assigned to the DataContext.

Then in your refresh button logic you call:

_model.Url = txtFeed.Text;
_model.GetFeed();

What you ultimately want to do is put another layer in the middle. This is the view model. The View model is as you may have guessed a model of the view.

The view model's job is to collect information about the state of the view and to expose the data from the model that is to be presented by the view. It also can hold current ui state information - f.e. which row in the table is selected, since some command may act on that later. In essence it allows to abstract all the logic of the view from your code. Your commands operate on things like which row is selected - regardless of which type of control did the selection.

Upvotes: 1

Related Questions