Nghia Nguyen
Nghia Nguyen

Reputation: 2665

parse xml and binding data to listbox

It's very simple task, but I struggle for hours. I have parse xml from web sources and bind them to listbox. Now I want to make an index for each items binded to list box, something like this:

1.Title   2.Title   3.Title
  Author    Author    Author
  Date      Date      Date

Here is what I have so far:

                <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Name="stkPnl"  Orientation="Horizontal" Margin="15,0" MouseEnter="stkPnl_MouseEnter" MouseLeave="stkPnl_MouseLeave">
                        <Image x:Name="imageAV" Source="{Binding avlink}" Height="80" Width="80" 
                               Stretch="UniformToFill" MouseLeftButtonUp="imageAV_MouseLeftButtonUp" ImageFailed="imageAV_ImageFailed"/>
                        <StackPanel Orientation="Vertical" Margin="10,0,0,0" MouseLeftButtonUp="StackPanel_MouseLeftButtonUp">                                                               
                            <TextBlock Text="{Binding nickname}" Width="Auto" />                               
                            <TextBlock Text="{Binding track}" FontWeight="Bold" Width="Auto"/>
                            <TextBlock Text="{Binding artist}" Width="Auto"/>
                        </StackPanel>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>

and MainPage.xaml.cs

        private void DoWebClient()
    {
        var webClient = new WebClient();
        webClient.OpenReadAsync(new Uri("http://music.mobion.vn/api/v1/music/userstop?devid="));
        webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(webClient_OpenReadCompleted);

    }

    void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
    {
        using (var reader = new StreamReader(e.Result))
        {

            string s = reader.ReadToEnd();
            Stream str = e.Result;
            str.Position = 0;
            XDocument xdoc = XDocument.Load(str);

            var data = from query in xdoc.Descendants("user")
                       select new mobion
                       {
                           avlink = (string)query.Element("user_info").Element("avlink"),
                           nickname = (string)query.Element("user_info").Element("nickname"),
                           track = (string)query.Element("track"),
                           artist = (string)query.Element("artist"),
                       };
            listBox.ItemsSource = data;
        }
    }

As you see I only have nickname, track and artist, if I want to add an index that increase for each listboxItem, how can I do that? Thank you for reading this question.

Upvotes: 1

Views: 1803

Answers (2)

Matt Lacey
Matt Lacey

Reputation: 65566

Assuming you've an appropriate field in you mobion class (which you can bind to in the view), you can use an incrementing counter to populate this field as the document is iterated over.

int[] counter = { 1 };       

var data = from query in xdoc.Descendants("user")
           select new mobion
           {
               index = counter[0]++,
               avlink = (string)query.Element("user_info").Element("avlink"),
               nickname = (string)query.Element("user_info").Element("nickname"),
               track = (string)query.Element("track"),
               artist = (string)query.Element("artist"),
           };

Note that counter is an array of int rather than just an int to prevent accessing a modified closure.

Upvotes: 0

CodeZombie
CodeZombie

Reputation: 5377

I know it's ugly, but it's an idea: Create a wrapper class for around your mobion class:

public class mobionWrapper : mobion
{
    public int Index { get; set; }
}

Instead of selecting mobion instances you select mobionWrapper instances:

var data = from query in xdoc.Descendants("user")
            select new mobionWrapper
            {
                avlink = (string)query.Element("user_info").Element("avlink"),
                nickname = (string)query.Element("user_info").Element("nickname"),
                track = (string)query.Element("track"),
                artist = (string)query.Element("artist"),
            };

After binding the your data, set the Index property of your wrapper class:

listBox.ItemsSource = data;

for(int i = 0; i < listBox.Items.Count; i++)
{
    var item = listBox.Items[i] as mobionWrapper;
    item.Index = i + 1;
}

Now you need a new TextBlock and bind it to the Index property:

<TextBlock Text="{Binding Index}" Width="Auto" />

Worked for me. Keep in mind that the index might be invalid after sorting or filtering the data display.

Upvotes: 1

Related Questions