Tech Off Thread

12 posts

Binding array to ListBox WPF

Back to Forum: Tech Off
  • User profile image
    fjvwj

    Hi, I'm currently messing around with WPF and I can't seem to get this done right. I'm trying to bind a string array to a ListBox, but when I run the program, the ListBox is empty.

    public Window()
    {
        string[] names = { "foo", "soo", "too" };
       
        listBox.ItemsSource = names;
    }

    If I do this:

    public Window()
    {
        string[] names = { "foo", "soo", "too" };
       
        listBox.ItemsSource = names;
        listBox.DisplayMemberPath = "Length";
    }

    then the ListBox displays 3,3,3.

    How do I get the ListBox to  display the strings.

    Thanks.

  • User profile image
    footballism

    Your first code snippet can actually do the trick.

    Sheva

  • User profile image
    JChung2006

    Don't put your code in the constructor, or it might run before the InitializeComponent() call that sets up the WPF controls from your XAML.

    You could use the Loaded event.

    MyPage.xaml:
    <Page
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      x:Class="WPF1.MyPage"
      Loaded="MyPage_Loaded">
        <ListBox Name="listBox">
      </ListBox>
    </Page>

    MyPage.xaml.cs:
    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Navigation;

    namespace WPF1
    {
      public partial class MyPage : System.Windows.Controls.Page
      {
        public MyPage()
        {
          InitializeComponent();
        }

        void MyPage_Loaded(object sender, RoutedEventArgs e)
        {
          string[] names = { "foo", "bar", "xyzzy" };
          listBox.ItemsSource = names;
        }
      }
    }

  • User profile image
    tamir

    The right way to do it is by using Binding

    <Window.Resources>

    <ObjectDataProvider x:Key="data" ObjectType="{x:Type l:MyNames}"/>

    </Window.Resources>

    <StackPanel>

    <ListBox ItemsSource="{Binding Source={StaticResource data}}"/>

    -----------------

    public class MyNames : List<string>

    {

    public MyNames()

    {

    this.Add("foo");

    this.Add("soo");

    this.Add("too");

    }

    }

    But you also can show you string array in the listbox this way

    <ListBox Name="list"/>
    ------------------

    public Window1()

    {

    InitializeComponent();

    list.Loaded += new RoutedEventHandler(list_Loaded);

    }

    string[] names = { "foo", "soo", "too" };

    void list_Loaded(object sender, RoutedEventArgs e)

    {

    list.ItemsSource = names;

    }

  • User profile image
    JChung2006

    tamir wrote:
    The right way to do it is by using Binding

    Correction:  that's the declarative way to do it, not the "right" way.

  • User profile image
    tamir

    The "right" way, I mean is to use Binding instead of regular reference Smiley

  • User profile image
    footballism

    tamir wrote:
    The "right" way, I mean is to use Binding instead of regular reference Smiley

       It depends on the type of scenario you wanna enable, if you simply show the data, assign the source collection directly to ItemsSource should be more appropriate, since it doesn't incur the performance implication which binding brings.
       If you wanna enable notification from data source to the UI element, then Binding should be the right way to do it.

    Sheva

  • User profile image
    tamir

    It's really hard for me to imagin, that I need only to show someting. If I do not want it to be updated, when the source changes, put it into resources or use directly in markup (e.g. state options). For all other cases (when you need to set this information from code-behind), you might want to bind to data, to be sure it'll be updated on source update

  • User profile image
    JChung2006

    tamir wrote:
    It's really hard for me to imagine, that I need only to show someting.

    Standard operating procedure for reporting, which is typically read-only data binding.

  • User profile image
    Happy

    JChung2006 said:

    Don't put your code in the constructor, or it might run before the InitializeComponent() call that sets up the WPF controls from your XAML.

    You could use the Loaded event.

    MyPage.xaml:
    <Page
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      x:Class="WPF1.MyPage"
      Loaded="MyPage_Loaded">
        <ListBox Name="listBox">
      </ListBox>
    </Page>

    MyPage.xaml.cs:
    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Navigation;

    namespace WPF1
    {
      public partial class MyPage : System.Windows.Controls.Page
      {
        public MyPage()
        {
          InitializeComponent();
        }

        void MyPage_Loaded(object sender, RoutedEventArgs e)
        {
          string[] names = { "foo", "bar", "xyzzy" };
          listBox.ItemsSource = names;
        }
      }
    }

    void list_Loaded(object sender, RoutedEventArgs e)

    {

    list.ItemsSource = names;

    }

    /*I want to add one more line */

    void list_Loaded(object sender, RoutedEventArgs e)

    {

    list.ItemsSource = names;

    list.Items.Add("Happy"); /* Operation is not valid while ItemsSource is in use. Access and modify elements with ItemsControl.ItemsSource instead.*/

    }

    hi all I want to add some more Item after set Itemsource can u help me how to add after Set Itemsoure please Help me out

     

     

    Thanks and regards

    HAPPY

  • User profile image
    pivoo

    @tamir:Hi!

    I read your answer and have some questions (maybe not too smart Smiley )

    I have Visual Studio 2008, NET Framework 3.5/SP1

    <ObjectDataProvider x:Key="data" ObjectType="{x:Type l:MyNames}"/>

    1. Should I use x:Name instead of x:Key ?

    2. What is "I:" here? I couldn't find such namespace in your code. I can't find the right namespace nam—É for me to compile such code Sad

    3. The main question. I have class:

     

    public class A
    {
    private readonly string _name;
    public A(string n)
    {
    _name = n;
    }
    public ShowName
    {
    get {return _name;}
    }
    
    public DoSmth
    {
    // Do something
    }

    I want to render list of class A objects as TextBlock with ShowName as text, and button wich will call DoSmth for this object. How can I do it?

    Now I am trying something like this:

                    <StackPanel x:Name="spLstOfA">
                        <ListBox Grid.Row="0" x:Name="lstOfA">
                            <ListBox.ItemTemplate>
                                <DataTemplate>
                                    <StackPanel Orientation="Horizontal">
                                        <TextBlock Text="{Binding Path=ShowName}" />
                                        <Button Command="{Binding Path=DoSmth}" >Button!!</Button>
                                        
                                    </StackPanel>
                                </DataTemplate>
                            </ListBox.ItemTemplate>
                        </ListBox>
                    </StackPanel>

    P/s I am not familiar with WPF

  • User profile image
    spivonious

    @pivoo: You're almost there. You just need to set the ItemsSource property of the ListBox to your list of A objects. While there are other ways to do this, the easiest way is to set it in the code-behind during the Initialized event.

    To answer your other questions:

    1. No, this line goes in the <Window.Resources> section, so a key is needed.

    2. You'll need to add a namespace to reference your assembly. <xmlns local="clr-namespace:MyAssembly"> will let you reference your own classes in XAML by prefixing them with local, such as <local:A>.

     

    I think you'd benefit greatly by getting a book on WPF. I found Apress' "Pro WPF in C# 2008" to be very helpful. I'm sure there's an updated edition now for .NET 4.

Comments closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums, or Contact Us and let us know.