Domanda

i am using ObservableCollection to bind to the list box some strings: Here is my code for SongFinder:

     string title, downloadlink, artist, duration;
    private readonly HtmlWeb web = new HtmlWeb();
    public string Title
    {
        get { return title; }
        set { title = value; }
    }
    public string DownloadLink
    {
        get { return downloadlink; }
        set { downloadlink = value; }
    }
    public string Artist
    {
        get { return artist; }
        set { artist = value; }
    }
    public string Duration
    {
        get { return duration; }
        set { duration = value; }
    }

    public SongFinder(string pageuri)
    {

    }
    public void Mp3Monkey(string pageUri)
    {
        HtmlDocument doc = web.Load(pageUri);
        HtmlNode documentNode = doc.DocumentNode;
        doc.OptionUseIdAttribute = true;
        var xpath = "//div[@class='dd']/noindex/div";
        HtmlNodeCollection col = documentNode.SelectNodes(xpath);


        foreach (var n in col)
        {
            downloadlink = "https://www.mp3monkey.net/audio/" + n.SelectSingleNode("span[@id='oid']").InnerText + "/" + n.SelectSingleNode("span[@id='aid']").InnerText + "/" +
                        n.SelectSingleNode("span[@id='autor']").InnerText + "_-_" + n.SelectSingleNode("span[@id='title']").InnerText.Replace(" ", "_") + ".mp3";

            artist = n.SelectSingleNode("span[@id='autor']").InnerText;
            title = n.SelectSingleNode("span[@id='title']").InnerText;
            TimeSpan t = TimeSpan.FromSeconds(double.Parse(n.SelectSingleNode("span[@id='time']").InnerText));
            string answer = string.Format("{0:D2}:{1:D2}:{2:D2}",
             t.Hours,
             t.Minutes,
             t.Seconds);
            duration = answer;
        }
    }

Here is my code to bind the observable collection to the listbox:

    <ListBox x:Name="list" ItemsSource="{Binding}" HorizontalAlignment="Left" Height="365" Margin="73,187,0,0" VerticalAlignment="Top" Width="460">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock Text="{Binding Title}"/>
                    <TextBlock Text="{Binding Artist}"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

Here is my Code-Behind;

       this.DataContext = net;

        string Mp3Monkey1 = "Eminem Mp3 Download.htm";
        SongFinder find = new SongFinder(@"D:\books\" + Mp3Monkey1);
        find.Mp3Monkey(@"D:\books\" + Mp3Monkey1);
        net.Add(find);

Now the problem i am having is that when all the info is loaded the ListBox only displays the last song in the collection. Please Help!! And if i try to debug without binding it works fine and load all info for every song.

Why is that i want to know??

Any Help Would be appreciated

È stato utile?

Soluzione

On your code you do overwrite your properties (Artist, Duration, etc ...) so obviously you will only see the last song that the foreach loop processed.

Solution:

Use a collection that you will fill in the loop by creating a new Song from each node in your HTMLNodeCollection

Example:

Code

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;

namespace WpfApplication1
{
    public partial class MainWindow
    {
        public MainWindow()
        {
            InitializeComponent();
            Loaded += MainWindow_Loaded;
        }

        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            // Let's pretend this is your HtmlNodeCollection 
            var collection = new List<Song>
            {
                new Song
                {
                    Artist = "Joeski & Chus",
                    Title = "El Amor",
                    Duration = TimeSpan.FromMinutes(5).TotalSeconds
                },
                new Song
                {
                    Artist = "Dano & Joeski",
                    Title = "For your love",
                    Duration = TimeSpan.FromMinutes(10).TotalSeconds
                },
            };

            // Build objects from your HTML nodes ...
            var songs = new ObservableCollection<Song>();
            foreach (Song song in collection)
            {
                songs.Add(song);
            }

            DataContext = songs;
        }
    }

    internal class Song
    {
        public string Artist { get; set; }
        public string Title { get; set; }
        public double Duration { get; set; }
    }
}

XAML

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:wpfApplication1="clr-namespace:WpfApplication1"
        Title="MainWindow"
        Width="525"
        Height="350">
    <Grid>
        <ListBox ItemsSource="{Binding}">
            <ListBox.ItemTemplate>
                <DataTemplate DataType="wpfApplication1:Song">
                    <Border Margin="2"
                            BorderBrush="Red"
                            BorderThickness="1">
                        <StackPanel>
                            <TextBlock Text="{Binding Artist, StringFormat='{}Artist: {0}'}" />
                            <TextBlock Text="{Binding Title, StringFormat='{}Title: {0}'}" />
                            <TextBlock Text="{Binding Duration, StringFormat='{}Duration: {0}'}" />
                        </StackPanel>
                    </Border>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Window>

Result

enter image description here

EDIT

Example with your code:

var songs = new ObservableCollection<Song>();
foreach (var n in col)
{
    Song song = new Song();
    downloadlink = "https://www.mp3monkey.net/audio/" + n.SelectSingleNode("span[@id='oid']").InnerText + "/" + n.SelectSingleNode("span[@id='aid']").InnerText + "/" +
                n.SelectSingleNode("span[@id='autor']").InnerText + "_-_" + n.SelectSingleNode("span[@id='title']").InnerText.Replace(" ", "_") + ".mp3";

    song.Artist = n.SelectSingleNode("span[@id='autor']").InnerText;
    song.Title = n.SelectSingleNode("span[@id='title']").InnerText;
    // etc ...

    songs.Add(song);    
}

DataContext = songs;

Make sure you do use my Song class and the ListBox along with the DataTemplate I've defined in XAML.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top