Search code examples
c#xamlwindows-store-apps

Dynamically create list of buttons and pass data in it?


I am new to C# and I Self-teach myself C#. I am trying to create my first win8 store app in C# XAML. The app will be for my use only and won't be published to the store. The app web scrapes a site, and it collects some links from it and their descriptions and fills the list. The list has link and description and looks like this: link: www.google.com description: google

link: www.yahoo.com description: yahoo

My first problem is that i don't understand how to pass this data to the XAML page. And my other problem is how do i create a dynamic list of buttons so if my list has 10 element i want 10 buttons on XAML page. If my list has 5 elements i want 5 buttons on XAML page. And each button must have it's Content set to description from my list. When i click on a button i want to pass the link that belongs to description and open another XAML page where i can use the link and do something with it.

My MainPage.xaml.cs looks lik this:

{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
    public ObservableCollection<MyApp.HtmlParser.LinkItem> LinkItems { get; set; } 

    public MainPage()
    {
     
        this.InitializeComponent();
    }

    /// <summary>
    /// Invoked when this page is about to be displayed in a Frame.
    /// </summary>
    /// <param name="e">Event data that describes how this page was reached.  The Parameter
    /// property is typically used to configure the page.</param>
    protected async override void OnNavigatedTo(NavigationEventArgs e)
    {
        HtmlParser pars = new HtmlParser();
        pars.Uri = "http://some website.something/";
        //LinksItems = await pars.Parse();
        ObservableCollection<MyApp.HtmlParser.LinkItem> LinksItem = await pars.Parse();
        ListLinks.DataContext = LinkItems;
    }
}

}

My HtmlParser Class looks like this:

{
class HtmlParser
{

    private string sUri;

    public string Uri
    {
        get { return this.sUri; }
        set { this.sUri = value; }
    }

    public class LinkItem
    {
        public string link { get; set; }
        public string description { get; set; }

        public LinkItem(string Link, string Description)
{
    this.link = Link;
    this.description = Description;

}

    }
   
    public HtmlParser()
    {
        this.sUri = string.Empty;
    }
    public async Task<ObservableCollection<LinkItem>> Parse()

    {
        ObservableCollection<LinkItem> listDesc = new ObservableCollection<LinkItem>();
        // Initialize http client.
         HttpClient httpClient = new HttpClient();
        var message = new HttpRequestMessage(HttpMethod.Get, this.sUri);
        message.Headers.Add("User-Agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");
        var response = await httpClient.SendAsync(message);
        var result = response.Content.ReadAsStringAsync().Result;

        HtmlAgilityPack.HtmlNode.ElementsFlags.Remove("option");

        HtmlDocument document = new HtmlDocument();
        document.LoadHtml(result);

        //pars web page
        //var options = document.DocumentNode.Descendants("option").Skip(1)
        //    .Select(n => new
        //    {
        //        Value = n.Attributes["value"].Value,
        //        Text = n.InnerText
        //    })
        //    .ToList();

        //pars mobile web page
        var options = document.DocumentNode.Descendants("a").Skip(1)
         .Select(n => new
         {
             Value = n.Attributes["href"].Value,
             Text = n.InnerText,

         })
         .ToList();

        foreach (var e in options)
        {
            // Add results to list:
            listDesc.Add(new LinkItem( "http://mobile.blitz-cinestar.hr/" + e.Value, e.Text));
        }
        return listDesc;
    }

}

}

My XAML looks like this

<Page
x:Class="MyApp.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<ListView x:Name="ListLinks" ItemsSource="{Binding}"
      HorizontalAlignment="Left" Height="495" VerticalAlignment="Top" Width="382">
</ListView>

Sorry for my bad English.


Solution

  • You should probably renamed MyList to LinkItem, which holds a link and its description;

    1. Add a property of type ObservableCollection<LinkItem> and populate it (in this example, ill name it MyLinks)
    2. Add a ListView to your MainPage.xaml
    3. Set the list view's ItemsSource property to {Binding MyLinks}. By now, you should have a listview showing the "MyAppNamespace.LinkItem" string for each item
    4. Create an ItemTemplate for each LinkItem, where you display a Button and set its Content property to {Binding Description}
    5. Create a handler for the Click event

    I hope that's enough to send you on the right path. Also, you should probably start by doing some of the Windows 8 tutorials to better grasp some of these concepts.

    Edit

    You didn't follow my instructions correctly.. Try this: Add a property to your MainPage and populate that with LinkItems:

    public sealed partial class MainPage : Page
    {
        ObservableCollection<LinkItem> LinkItems {get; set;} // <---------
    
        public MainPage()
        {
            this.InitializeComponent();
        }
    
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            HtmlParser pars = new HtmlParser();
            pars.Uri = "http://some website.something/";
            LinksItems = await pars.Parse();    //<-------------
        }
    }
    

    Make the parser return a populated collection:

    public async Task<ObservableCollection<LinkItem>> Parse()
        {
            ObservableCollection<LinkItem> listDesc = new ObservableCollection<LinkItem>();
            //...
            return listDesc;
        }
    

    Change the binding to LinkItems (the name of the collection you created above):

    <ListView x:Name="ListLinks" ItemsSource="{Binding LinkItems}"
          HorizontalAlignment="Left" Height="495" VerticalAlignment="Top" Width="382">
    </ListView>