Search code examples
c#.netwpflistboxstackpanel

ListBox Data Control Isn't Showing Information


First time using a ListBox and after following this , I'm having issues having data actually display. The ListBox is just empty and white with no text in it.

I made a separate textbox to test an individual "Tweet" object out and it is indeed outputting what I want it to. I think my issue either lies in XAML or Tweets. But nothing looks out of place.

Tracing reveals that Tweets successfully adds a proper Tweet object with what I need. But my ListBox Count is always 0.

<Grid Opacity="0.8">
        <Grid.Resources>
            <local:Tweets x:Key="tweets"/>
        </Grid.Resources>
        <Rectangle Fill="Gray" Margin="1523,0,0,729" Height="321" Width="389">
            <Rectangle.Effect>
                <DropShadowEffect/>
            </Rectangle.Effect></Rectangle>
        <ListBox ItemsSource="{StaticResource tweets}" Height="321" Margin="340,40,1096,0" x:Name="twitterBox" VerticalAlignment="Top" Width="476">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" Height="132">
                        <!--<Image Source="{Binding imgSrc}" Height="73" Width="73" VerticalAlignment="Top" Margin="0,10,8,0"/>-->
                        <StackPanel Width="370">
                            <TextBlock Text="{Binding user}"  FontSize="28" />
                            <TextBlock Text="{Binding tweet}" TextWrapping="Wrap" FontSize="24" />
                        </StackPanel>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
  </Grid>

In my cs:

 public class Tweet
{
       public String imgSrc { get; set; }
        public String user { get; set; }
        public String tweet { get; set; }

        public Tweet(String user, String tweet, String img)
        {
            this.imgSrc = img;
            this.user = user;
            this.tweet = tweet;
        }
}

public class Tweets : ObservableCollection<Tweet>
{
    public Tweets()
    {

    }

    public void addTweet(Tweet tweet)
    {
        Add(tweet);
    }
}


public void SomeFunction()
{
      Tweets myTwitter = new Tweets();
      myTwitter.addTweet(new Tweet(tweet.User.ScreenName, tweet.Text, tweet.User.ProfileImageUrl));
}

Solution

  • ItemTemplate code is ok but you should remove this Margin="1523,0,0,729".

    ListBox is empty because items source is empty. You should add some items.

    To add items in XAML you should add default constructor to Tweet class.

    public class Tweet
    {
        public String imgSrc { get; set; }
        public String user { get; set; }
        public String tweet { get; set; }
    
        public Tweet(){}
    
        public Tweet(String user, String tweet, String img)
        {
            this.imgSrc = img;
            this.user = user;
            this.tweet = tweet;
        }
    }
    

    And now you can write something like this:

    ...
    <Grid.Resources>
        <local:Tweets x:Key="tweets">
            <local:Tweet imgSrc="imgSrc1" user="user1" tweet="tweet1" />
            <local:Tweet imgSrc="imgSrc2" user="user2" tweet="tweet2" />
        </local:Tweets>
    </Grid.Resources>
    ...
    

    Result:

    enter image description here

    Add items in code-behind.

    To do that you should use function: FindResource (msdn).

    XAML:

    <Grid Name="mainGrid" Opacity="0.8">
        <Grid.RowDefinitions>
            <RowDefinition Height="30" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.Resources>
            <local:Tweets x:Key="tweets">
                <local:Tweet imgSrc="imgSrc1" user="user1" tweet="tweet1" />
                <local:Tweet imgSrc="imgSrc2" user="user2" tweet="tweet2" />
            </local:Tweets>
        </Grid.Resources>
        <Button Content="Add new item" Click="Button_Click" />
        <ListBox x:Name="twitterBox" ItemsSource="{StaticResource tweets}" 
                 VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
                 Grid.Row="1">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" Height="132">
                        <!--<Image Source="{Binding imgSrc}" Height="73" Width="73" VerticalAlignment="Top" Margin="0,10,8,0"/>-->
                        <StackPanel Width="370">
                            <TextBlock Text="{Binding user}"  FontSize="28" />
                            <TextBlock Text="{Binding tweet}" TextWrapping="Wrap" FontSize="24" />
                        </StackPanel>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
    

    Code-behind:

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        var coll = mainGrid.FindResource("tweets") as Tweets;
        if (coll != null)
        {
            coll.Add(new Tweet("user", "name", "url"));
        }
    }
    

    Second solution:

    The better solution will be if you will create an instance of class Tweets in code behind.

    XAML:

    <Grid Name="mainGrid" Opacity="0.8">
        <Grid.RowDefinitions>
            <RowDefinition Height="30" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>      
        <Button Content="Add new item" Click="Button_Click" />
        <ListBox x:Name="twitterBox" ItemsSource="{Binding tweets}" 
                 VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
                 Grid.Row="1">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" Height="132">
                        <!--<Image Source="{Binding imgSrc}" Height="73" Width="73" VerticalAlignment="Top" Margin="0,10,8,0"/>-->
                        <StackPanel Width="370">
                            <TextBlock Text="{Binding user}"  FontSize="28" />
                            <TextBlock Text="{Binding tweet}" TextWrapping="Wrap" FontSize="24" />
                        </StackPanel>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
    

    Code-behind:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
    
            tweets = new Tweets();
    
            tweets.Add(new Tweet("user1", "name1", "url1"));
            tweets.Add(new Tweet("user2", "name2", "url2"));
            tweets.Add(new Tweet("user3", "name3", "url3"));
    
            this.DataContext = this;
        }
    
        public Tweets tweets { get; set; }
    
        private void Button_Click(object sender, RoutedEventArgs e)
        {          
            tweets.Add(new Tweet("user4", "name4", "url4"));
        }
    }