locked
Image Binding to ListBox from central source (C#/XAML/W8.1)

    Question

  • I want to have a central repository of Text/Image Lists to use in my ListBoxes.

    The following is code and XAML is used:

    ////////////////////////////////////////////////// Assets/ListsData.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Windows.ApplicationModel.Resources;

    namespace FavouriteStores.Assets
    {

        public class StoreList
        {
            private string _sID;
            public string sID
            {
                get { return _sID; }
                set { _sID = value; }
            }

            private string _sName;
            public string sName
            {
                get { return _sName; }
                set { _sName = value; }
            }

            private string _sImage;
            public string sImage
            {
                get { return _sImage; }
                set { _sImage = value; }
            }

            private int _sSort;
            public int sSort
            {
                get { return _sSort; }
                set { _sSort = value; }
            }

            public StoreList() { }
            public StoreList(string StoreID, string StoreName, string StoreImage, int StoreSort)
            {
                sID = StoreID;
                sName = StoreName;
                sImage = StoreImage;
                sSort = StoreSort;
            }
            public override string ToString() { return sName; }
        }

        public class GetStore
        {
            static ResourceLoader loader = new ResourceLoader();

            private List<StoreList> Stores { get; set; }

            public GetStore()
            {
                Stores = new List<StoreList>();
                Stores.Add(new StoreList("AZfr", "amazon.fr", "Assets/" + "fr165x28flag.png", 1));
                Stores.Add(new StoreList("AZit", "amazon.it", "Assets/" + "it165x28flag.png", 2));

                Stores.Sort((x, y) => x.sSort.CompareTo(y.sSort)); //Ascending
            }

            public List<StoreList> GetStoreList()
            {
                return Stores;
            }    
        }
    }

    ////////////////////////////////////////////////// MainPage.xaml.cs

    using FavouriteStores.Assets;
    //more using... etc. are here

    namespace FavouriteStores
    {
        public sealed partial class MainPage : Page
        {
            private GetStore getstorelist = new GetStore();

            public MainPage()
            {
                this.InitializeComponent();
                this.lstboxStoresDynamic.DataContext = getstorelist.GetStoreList();
            }
        }
    }

    ////////////////////////////////////////////////// MainPage.xaml

            <ListBox x:Name="lstboxStoresDynamic" x:Uid="StoresList" ItemsSource="{Binding}" SelectedValuePath="sID" SelectionMode="Single" HorizontalAlignment="Left" Height="290" Margin="400,22,0,0" VerticalAlignment="Top" Width="300" FontSize="17" Background="White" BorderBrush="#EF7F1A" BorderThickness="1" IsHoldingEnabled="False" IsRightTapEnabled="False" ToolTipService.ToolTip="Select your favourite Store" IsSynchronizedWithCurrentItem="False" IsTabStop="True" TabIndex="1" FontFamily="Segoe UI" FontWeight="Bold" Tapped="lstboxStores_Click" >
                <ListBoxItem Tag="AZcom" x:Uid="DefaultStoreListUS" ToolTipService.ToolTip="amazon.com (U.S.A.)" >
                    <Image Source="{Binding  sImage}" Stretch="None" Width="165" Height="28"  />
                </ListBoxItem>
            </ListBox>

    //////////////////////////////////////////////////

    THE PROBLEM IS: Instead of showing my bitmap PNG, it just shows the text:
    amazon.fr
    amazon.it

    No matter how I try to adjust the code, I'm not able to get it to work.

    THE SECOND PROBLEM IS: I'm generally no able to pick out the other properties of the binding like sID, sImage, sSort. So, depending on which item is selected in the ListBox, I would want to have e.g. sID returned, using something like this (which works with the Tag property (without binding):
    string selectedTagx = ((ListBoxItem)lstboxStoresDynamic.SelectedItem).sID.ToString();

    That particular line ends up with this error after F5:
    'Windows.UI.Xaml.Controls.ListBoxItem' does not contain a definition for 'sID' and no extension method 'sID' accepting a first argument of type 'Windows.UI.Xaml.Controls.ListBoxItem' could be found (are you missing a using directive or an assembly reference?)



    Friday, March 07, 2014 4:36 PM

Answers

  • You could add an extra property to the StoreList class that transforms the string path to a valid image source:

    public ImageSource Image
    {
        get
        {
            return new BitmapImage(new Uri("ms-appx:///" + this.sImage));
        }
    }

    Then you can bind to Image instead of sImage:

    <Image Source="{Binding Image}" Stretch="None" Width="165" Height="28" />
    About your second problem: you're casting to a ListBoxItem which indeed does not have a sID property. Try this:
    string selectedTagx = ((StoreList)lstboxStoresDynamic.SelectedItem).sID.ToString();

    Friday, March 14, 2014 10:19 AM
  • Hi Diederik :-)
    First of all THANK YOU. This is the kind of help I was looking for.
    The second problem is solved. Spot on. Brilliant. Your code solved it. (and I also saw now how to properly submit code in the correct fashion ;-)

    string selectedTagx = ((StoreList)lstboxStoresDynamic.SelectedItem).sID.ToString();

    The first problem still exists. I have been experimenting, so its best if I submit the updated code in a separate post.

    Again thank you.

    Friday, March 14, 2014 3:32 PM

All replies

  • Hi LightningBlitz,

    Seems you have problem with binding, I would suggest you change this line, you should be able to see the correct path. The following code should help you with the first question.

    //public override string ToString() { return sName; }
    public override string ToString() { return sImage; }
    

    I think you've also noticed that the Path is only a String but not a Uri, because you override the ToString() method, you bind a object.ToString() to the item and therefore the string is displayed.

    For more binding information, I would suggest you to read this for more information: Quickstart: Data binding to controls, you have to use a ItemTemplate/DataTemplate for helping with binding stuff.

    --James


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    Monday, March 10, 2014 4:52 AM
    Moderator
  • Thanks for your reply. This doesn't solve my problem though. I was looking for some hands-on help here. Code to correct the problem. I have read several articles about data binding, but nothing shows me how to do it. The apparently unusual setting here is that I want to have the lists created in a central source and not on my MainPage.

    I'm hoping that somebody else can provide a real answer to solve my problem. This is my first post and I am somewhat disappointed for the lack of real help provided.

    Friday, March 14, 2014 9:55 AM
  • You could add an extra property to the StoreList class that transforms the string path to a valid image source:

    public ImageSource Image
    {
        get
        {
            return new BitmapImage(new Uri("ms-appx:///" + this.sImage));
        }
    }

    Then you can bind to Image instead of sImage:

    <Image Source="{Binding Image}" Stretch="None" Width="165" Height="28" />
    About your second problem: you're casting to a ListBoxItem which indeed does not have a sID property. Try this:
    string selectedTagx = ((StoreList)lstboxStoresDynamic.SelectedItem).sID.ToString();

    Friday, March 14, 2014 10:19 AM
  • Hi Diederik :-)
    First of all THANK YOU. This is the kind of help I was looking for.
    The second problem is solved. Spot on. Brilliant. Your code solved it. (and I also saw now how to properly submit code in the correct fashion ;-)

    string selectedTagx = ((StoreList)lstboxStoresDynamic.SelectedItem).sID.ToString();

    The first problem still exists. I have been experimenting, so its best if I submit the updated code in a separate post.

    Again thank you.

    Friday, March 14, 2014 3:32 PM
  • I have implemented the suggested code as follows:
    ListsData.cs

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Windows.ApplicationModel.Resources;
    using Windows.UI.Xaml.Media;
    using Windows.UI.Xaml.Media.Imaging;
    
    namespace FavouriteStores.Assets
    {
        public class StoreList
        {
            private string _sID;
            public string sID
            {
                get { return _sID; }
                set { _sID = value; }
            }
    
            private string _sName;
            public string sName
            {
                get { return _sName; }
                set { _sName = value; }
            }
    
            private string _sImage;
            public string sImage
            {
                get { return _sImage; }
                set { _sImage = value; }
            }
    
            public ImageSource Image
            {
                get
                {
                    return new BitmapImage(new Uri("ms-appx:///" + this.sImage));
                }
            }
    
            private int _sSort;
            public int sSort
            {
                get { return _sSort; }
                set { _sSort = value; }
            }
    
            public StoreList() { }
            public StoreList(string StoreID, string StoreName, string StoreImage, int StoreSort)
            {
                sID = StoreID;
                sName = StoreName;
                sImage = StoreImage;
                sSort = StoreSort;
            }
        }
    
    
        public class GetStore
        {
            static ResourceLoader loader = new ResourceLoader();
    
            private List<StoreList> Stores { get; set; }
    
            public GetStore()
            {
                Stores = new List<StoreList>();
                Stores.Add(new StoreList("AZfr", "amazon.fr", "Assets/" + "fr165x28flag.png", 1));
                Stores.Add(new StoreList("AZit", "amazon.it", "Assets/" + "it165x28flag.png", 2));
    
                Stores.Sort((x, y) => x.sSort.CompareTo(y.sSort));
            }
    
            public List<StoreList> GetStoreList()
            {
                return Stores;
            }
        }
    }
    MainPage.xaml.cs:
    using FavouriteStores.Assets;
     //more using... etc. are here
    
    namespace FavouriteStores
    {
        public sealed partial class MainPage : Page
        {
            private GetStore getstorelist = new GetStore();
    
            public MainPage()
            {
                this.InitializeComponent();
                this.lstboxStoresDynamic.DataContext = getstorelist.GetStoreList();
                this.lstboxStoresDynamic.DisplayMemberPath = "sName";
            }
        }
    }
    And lastly, MainPage.xaml:
            <ListBox x:Name="lstboxStoresDynamic" x:Uid="StoresList" ItemsSource="{Binding}" SelectedValuePath="sID" SelectionMode="Single" HorizontalAlignment="Left" Height="290" Margin="600,22,0,0" VerticalAlignment="Top" Width="300" FontSize="17" Background="White" BorderBrush="#EF7F1A" BorderThickness="1" IsHoldingEnabled="False" IsRightTapEnabled="False" ToolTipService.ToolTip="Select your favourite Store" IsSynchronizedWithCurrentItem="False" IsTabStop="True" TabIndex="1" FontFamily="Segoe UI" FontWeight="Bold" Tapped="lstboxStores_Click" >
                <ListBoxItem Tag="AZ" x:Uid="DefaultStoreListUS" ToolTipService.ToolTip="amazon stores" >
                    <Image Source="{Binding Image}" Stretch="None" Width="165" Height="28"  />
                </ListBoxItem>
            </ListBox>
    And still it only returns the contents of the sName variable (i.e. amazon.fr and amazon.it). I experimented a bit with the DisplayMemberPath (sImage or Image) and also not having this line in there altogether, but nothing made the PNG display.
    This would be fine too for items without an Image path. Which is what I eventually would want (i.e. items with an image path should show the image, and those without should show the sName).

    Again, thank you for your help. It's really appreciated.

    Friday, March 14, 2014 4:04 PM