that_guy
that_guy

Reputation: 2445

Windows Phone 7 Listbox not displaying

So I have a listbox I am trying to make for an "achievement page". Everything works good if I use a List but when I switch it to a List there is nothing displayed, not even from the xaml...

public partial class achievementPage : PhoneApplicationPage
{
    public string Description { get; set; }
    public string Type { get; set; }
    public achievementPage()
    {
        InitializeComponent();
        loadListbox();
    }
    public achievementPage(string achievementGet, string d1)
    {  
    }
    public void loadListbox()
    {
        achievementStoreage.loadData();
        List<achievementPage> achievementList = new List<achievementPage>();
        achievementList.Add(new achievementPage(achievementStoreage.achievement1, "This is a        test"));
        achievementList.Add(new achievementPage(achievementStoreage.achievement2, "This is    another test")); 
        //List<string> achievementList = new List<string>();
        //achievementList.Add("Sup");
        achievementListBox.ItemsSource = achievementList;
    }
}

<ListBox Name="achievementListBox" Margin="0,0,0,0" >
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Button Width="776" Height="120" BorderBrush="Black">
                <Button.Content>
                    <StackPanel Orientation="Horizontal" Height="50">
                        <StackPanel Orientation="Horizontal" Height="40">
                            <TextBlock Width="150" Foreground="Black" FontSize="22" Text="Description:" Height="40"/>
                        </StackPanel>
                    </StackPanel>
                </Button.Content>
            </Button>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

All I get is a blank page.. P.S don't worry about achievementStoreage, it is working properly.(just where I get stored data)

Upvotes: 0

Views: 746

Answers (2)

quetzalcoatl
quetzalcoatl

Reputation: 33566

Frankly, it seems that you are simply not allowed to use ItemTemplates along with UIElements as the items' DataContexts. I've tried with:

achievementListBox.ItemsSource = new [] {"a","b"};

and both items were visible and printed dummy "description" texts, but none of the following lines I've tried has presented anything at all:

achievementListBox.ItemsSource = new [] { new TextBlock(), new TextBlock()};
achievementListBox.ItemsSource = new [] { new Rectangle(), new Rectangle()};
achievementListBox.ItemsSource = new [] { new Grid(), new Grid()};

Trying with your custom page - the same. No items shown.

This is very misleading. The items were shown, but look at the lines above: the controls were created empty, with no contents set!.

It turns out, that if the ListBox detects that the Item is an UIElement, then it does not use the ItemTemplate, but it presents that UIElement directly!

achievementListBox.ItemsSource = new[] { new TextBlock() { Text = "bbb" }, new TextBlock() { Text = "eee" } };
achievementListBox.ItemsSource = new[] { new Rectangle() { Fill = new SolidColorBrush(Colors.Red), Width = 30, Height = 10 }, new Rectangle() { Fill = new SolidColorBrush(Colors.Green), Width = 30, Height = 10 } };

var gridA = new Grid() { Width = 110, Height = 40 }; gridA.Children.Add(new Rectangle() { Fill = new SolidColorBrush(Colors.Red) });
var gridB = new Grid() { Width = 110, Height = 40 }; gridB.Children.Add(new Rectangle() { Fill = new SolidColorBrush(Colors.Green) });
achievementListBox.ItemsSource = new[] { gridA, gridB };

All of the three above examples completely ignore the ListBox.ItemTemplate, and instead, they display two items directly: two textboxes, two rectangles, two larger rectangles (in a Grid).

Getting back to your case: It means that with your original setup, the ListBox would try to display the items directly too - as your custom Page is a UIElement. And indeed it did that! But your pages were ... empty. In the overloaded constructor you omitted the InitializeComponent(); that constructs the View by reading the XAML code. Here is a corrected example that displays a "Hello" three times: Once just because it lies on the page, and next two times because the ListBox rows are set to the same page.

Please excuse me for renaming the classes, I simply started a new project instead of pasting your code.
Please note that I had to add to the XAML some other controls, because the Pages used as the data items would be display as empty, because they would have no items set

public partial class MainPage : PhoneApplicationPage
{
    public string Description { get; set; }
    public string Type { get; set; }

    public MainPage()
    {
        InitializeComponent();
        loadListbox();
    }

    public MainPage(string achievementGet, string d1)
    {
        InitializeComponent();
        someText.Text = d1;
    }

    public void loadListbox()
    {
        achievementListBox.ItemsSource = new[] { new MainPage(null, "ddd"), new MainPage(null, "ccc") };
    }
}

<StackPanel>
    <TextBlock>
        <Run Text="Hello" />
        <Run Text=" " />
        <Run x:Name="someText" />
    </TextBlock>

    <ListBox Name="achievementListBox" Margin="0,0,0,0">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Width="150" Foreground="White"
                           FontSize="22" Text="This DataTemplate is IGNORED because the Item is UIElement"
                           Height="40"/>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</StackPanel>

I tried to shape the code in a similar manner to yours, just removed some lines not relevant to the problem. I hope this explains you everything now :)

Upvotes: 1

quetzalcoatl
quetzalcoatl

Reputation: 33566

Oh my. Why do create a list of achievementPages? On your achievementPage you will want to have a ListBox with items of type, like, AchievementItem, CompletedAchievement, NotCompletedAchievement, etc.

Currently, nothing shows up because your code probably throws StackoverflowException (not joking here:)). Look: your achievementPage constructor calls loadListBox that creates two achievementPages and adds them to the list. But creating two achievementPages causes again their constructors to be called two times, which invokes loadListBox two times, and so on..

-- edit: ok, no stackoverflow, I've just noticed the second constructor. You should stick to naming the classes with capital letters you know :) Anyways, putting a Page as a data item of a ListBox on a Page is a bad idea.

What you wanted to get should look more like:

public partial class AchievementPage : PhoneApplicationPage
{
    public string Description { get; set; }
    public string Type { get; set; }

    public AchievementPage()
    {
        InitializeComponent();
        loadListbox();
    }

    public void loadListbox()
    {
        var theList = new List<Achievement>();
        theList.Add(new Achievement{ AchvCount=3, AchvName="medals" });
        theList.Add(new Achievement{ AchvCount=2, AchvName="badges"  }); 
        theList.Add(new Achievement{ AchvCount=6, AchvName="zonks"  }); 

        achievementListBox.ItemsSource = achievementList;
    }
}

public class Achievement : DependencyObject
{
    public int AchvCount {get; set;}
    public string AchvName {get; set;}
}

<ListBox Name="achievementListBox" Margin="0,0,0,0">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="50" />
                    <ColumnDefinition Width="50" />
                    <ColumnDefinition Width="50" />
                </Grid.ColumnDefinitions>

                <TextBlock Grid.Column="0" Text="You've got:" />
                <TextBlock Grid.Column="0" Text="{Binding AchvCount}" />
                <TextBlock Grid.Column="0" Text="{Binding AchvName}" />
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Upvotes: 1

Related Questions