user1217169
user1217169

Reputation: 439

Adding and updating a databound listbox C# windows phone

I hope this question isnt to dumb, I've tried to search for a solution for 5hours, and mostly found helpfull stuff on this site, but I can not manage to fix my problem.

I have my Item Class with just this property:

public string ItemName { get; set; }

And a Class to hold Items:

public class ShoppingListItems
{
    public static List<Item> ItemCollection { get; set; }

    public ShoppingListItems()
    {
        ItemCollection = new List<Item>();
        AddAnItem("test");
    }

    public static void AddAnItem(string name)
    {
        ItemCollection.Add(new Item()
        {
            ItemName = name
        });
    }
}

And in my XAML file, binding related code is:

    xmlns:application="clr-namespace:ShoppingListTest"

    <Grid.Resources>
        <application:ShoppingListItems x:Key="ShoppingListItems" />
    </Grid.Resources>
    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0" DataContext="{StaticResource ShoppingListItems}">
        <ListBox x:Name="listBox1"  Height="Auto" ItemsSource="{Binding ItemCollection, Mode=TwoWay}">

                        <TextBlock x:Name="textBlock1" Text="{Binding ItemName}" FontSize="50"  />

And then in my MainPage.xaml.cs, in a method on KeyDown I have:

ShoppingListItems.AddAnItem(textBox1.Text);

The list works great, and shows "test" in the listBox, but adding to the list does not work, I have tried to look at some NotifyPropertyChanged stuff, without any luck.

Any idea on what I need to do to update the listBox? I would be soooo glad if anyone had some tips that would make this work!

Upvotes: 1

Views: 3363

Answers (3)

Zik
Zik

Reputation: 750

First I would recommend not using static members, it just seems to work better without.

Minor changes to ShoppingListItems:

public class ShoppingListItems
{
    public ObservableCollection<Item> ItemCollection { get; set; }

    public ShoppingListItems()
    {
        ItemCollection = new ObservableCollection<Item>();
        AddAnItem("test");
        AddAnItem("test2");
        AddAnItem("test3");
    }

    public void AddAnItem(string name)
    {
        ItemCollection.Add(new Item()
        {
            ItemName = name
        });
    }
}

Things are non-static, and List<> is ObservableCollection<> instead.

In the xaml:

<Grid>
    <Grid.Resources>
        <DataTemplate x:Key="itemLayout" DataType="{x:Type local:Item}">
            <TextBlock Text="{Binding ItemName}" FontSize="50" />
        </DataTemplate>
    </Grid.Resources>

    <ListBox x:Name="itemsListBox" Margin="2" ItemsSource="{Binding}" 
             ItemTemplate="{DynamicResource itemLayout}" 
             IsSynchronizedWithCurrentItem="True">
    </ListBox>
</Grid>

In the code-behind (the .cs file that corresponds to the xaml file):

    private ShoppingListItems _shoppingList;

    public MainWindow()
    {
        InitializeComponent();

        _shoppingList = new ShoppingListItems();
        itemsListBox.DataContext = _shoppingList.ItemCollection;
    }

EDIT:

What I did was put the data template up in the grid resources, while you put the data template as part of the list box resources. As far as I can tell the only real difference is if the template is part of the grid resources it could be used in multiple places. Say you wanted two shopping lists, maybe one for things you need and another for things you've already bought, and you wanted them formatted the same way, it would be best to put the template up in the grid so both lists could reference it. Since you only have one list it probably doesn't matter, either way is fine.

As for the Singleton pattern, see: Singleton on Wikipedia

The simplest approach would have your ShoppingListItems look like this:

public class ShoppingListItems
{
    private static ShoppingListItems _instance = new ShoppingListItems();
    public ObservableCollection<Item> ItemCollection { get; private set; }

    public static ShoppingListItems Instance { get { return _instance; } }

    private ShoppingListItems()
    {
        ItemCollection = new ObservableCollection<Item>();
        AddAnItem("test");
        AddAnItem("test2");
        AddAnItem("test3");
    }

    public void AddAnItem(string name)
    {
        ItemCollection.Add(new Item()
        {
            ItemName = name
        });
    }
}

Upvotes: 2

user1217169
user1217169

Reputation: 439

Thak you so much Zik, you code changes worked. In my XAML code I only changed to to ItemSource="{Binding}".

I really dont understand your last comment tho. Need to do some google search to try to understand, everthing I do is almost new for me :)

My XAML code for the list of items is like this now:

        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0" DataContext="{StaticResource ShoppingListItems}">
        <ListBox x:Name="listBox1"  Height="Auto" ItemsSource="{Binding}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid Margin="5" >
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
                        <TextBlock x:Name="textBlock1" Text="{Binding ItemName}" FontSize="50"  />
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>

And on the main grid I have this:

        <Grid.Resources>
        <application:ShoppingListItems x:Key="ShoppingListItems" />
    </Grid.Resources>

This seems to work great. But if it is better, what should I change to add your code like:

<DataTemplate x:Key="itemLayout" DataType="{x:Type local:Item}">

and

ItemTemplate="{DynamicResource itemLayout}" 
IsSynchronizedWithCurrentItem="True"

Upvotes: 0

Andrew
Andrew

Reputation: 905

Have you tried changing ItemCollection to be an ObservableCollection instead of a List?

Upvotes: 1

Related Questions