Reputation: 2513
I have a bit of code that reads a json response from an HTTP server, it then parses this and inserts the data into a ListBox
control.
The event I fire off when the download is complete is the following:
void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
DataContractJsonSerializer ser = null;
try
{
ser =
new DataContractJsonSerializer(typeof(ObservableCollection<UserLeaderboards>));
ObservableCollection<UserLeaderboards> users =
ser.ReadObject(e.Result) as ObservableCollection<UserLeaderboards>;
foreach (UserLeaderboards em in users)
{
int Fid = em.id;
string Fusername = em.username;
int Fscore = em.score;
lstbLeaders.Items.Add(Fid + Fusername + Fscore);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Now, when I do the items.add
I presume it's just joining up the 3 variables and adding it to one column in the ListBox
. This works fine and I see all 3 items joined up and displayed.
I want to separate this and make it look a bit nicer so I've created some XAML
to try and bind the variables to textblocks. The following is just binding the username. I also have a public class that get/sets all 3 variables.
<ListBox Height="346" HorizontalAlignment="Left" Margin="5,221,0,0"
Name="lstbLeaders" VerticalAlignment="Top" Width="446">
<DataTemplate>
<TextBlock Text="{Binding Source=Fusername}" />
</DataTemplate>
</ListBox>
When running the above I get nothing displayed at all. I have a feeling it's something simple?
Thanks.
Upvotes: 5
Views: 886
Reputation: 8882
To display a simple string your xaml should look like this:
<ListBox Height="346" HorizontalAlignment="Left" Margin="5,221,0,0"
Name="lstbLeaders" VerticalAlignment="Top" Width="446">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
<ListBox.ItemTemplate>
</ListBox>
and you have to provide an object instead of a simple string if you want to split the properties to make it look nicer. If you just add Fid + Fusername + Fscore
you will end up with a plain string.
<ListBox Height="346" HorizontalAlignment="Left" Margin="5,221,0,0"
Name="lstbLeaders" VerticalAlignment="Top" Width="446">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Id}" />
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding Score}" />
</StackPanel>
</DataTemplate>
<ListBox.ItemTemplate>
</ListBox>
You will need a view class:
public class UserView
{
public string Id {get;set;}
public string Name {get;set;}
public int Score {get;set;}
}
in your code behind:
var usersList = new List<UserView>();
foreach (UserLeaderboards em in users)
{
int Fid = em.id;
string Fusername = em.username;
int Fscore = em.score;
usersList.Add(new UserView { Id = Fid, Name = Fusername, Score = Fscore} );
}
lstbLeaders.ItemsSource = usersList;
Further notes:
ObservableCollection<UserLeaderboards>
direcectly to the list box?If there is no reason to convert to an other type skip the foreach
part of the code and simply set lstbLeaders.ItemsSource = users;
.
void webClient_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
try
{
var ser = new DataContractJsonSerializer(
typeof(ObservableCollection<UserLeaderboards>));
var users = ser.ReadObject(e.Result)
as ObservableCollection<UserLeaderboards>;
lstbLeaders.ItemsSource = users;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Take look at the MVVM pattern. If you want to work with XAML you should know about this. It simplifies your work and creates cleaner code.
If you want to add edit functionality or data can change you may need to implement INotifyPropertyChanged
on the View class.
You can use type inference which especially helps when working with cumbersome class names. var list = new ObservableCollection<SomeLongTypeName>()
saves much typing and screen estate.
Hungarian notation makes me cringe ;)
Upvotes: 5
Reputation: 912
I think you missed the ItemTemplate. Try this
<ListBox Height="346" HorizontalAlignment="Left" Margin="5,221,0,0" Name="lstbLeaders" VerticalAlignment="Top" Width="446">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Source=Fusername}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Upvotes: 1