使用数据绑定技术实现列表框功能

5

我有一段代码,从HTTP服务器读取JSON响应,然后解析数据并将其插入到ListBox控件中。

下载完成后触发的事件如下:

 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);
     }
 }

现在,当我执行items.add时,我假设它只是将3个变量连接起来并添加到ListBox中的一列。这很好用,我可以看到所有三个项目连接在一起并显示出来。
我想将其分开并使其更加美观,因此我创建了一些XAML来尝试将变量绑定到文本块。以下仅绑定用户名。我还有一个公共类,用于获取/设置所有3个变量。
<ListBox Height="346" HorizontalAlignment="Left" Margin="5,221,0,0" 
         Name="lstbLeaders" VerticalAlignment="Top" Width="446">
   <DataTemplate>                            
       <TextBlock Text="{Binding Source=Fusername}" />                           
   </DataTemplate>
</ListBox>

当我运行以上代码时,根本没有显示任何结果。我感觉这应该是个很简单的问题吧?
谢谢。
2个回答

5
要显示一个简单的字符串,你的xaml应该像这样:

要显示一个简单的字符串,你的xaml应该像这样:

<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>

如果您想将属性分隔开以使其更美观,您需要提供一个对象而不是一个简单的字符串。如果您只添加Fid + Fusername + Fscore,那么您最终会得到一个普通字符串。

<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>

您需要一个视图类:

视图类是必需的:

public class UserView
{
    public string Id {get;set;}
    public string Name {get;set;}
    public int Score {get;set;}
}

在代码后台:

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;

进一步说明:

  • 为什么不直接将ObservableCollection<UserLeaderboards>绑定到列表框上?

如果没有转换为其他类型的原因,请跳过代码中的foreach部分,直接设置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);
     }
}
  • 了解MVVM模式。如果你想使用XAML,你应该知道这个模式。它可以简化你的工作并创建更干净的代码。

  • 如果你想添加编辑功能或数据可能会改变,你可能需要在View类上实现INotifyPropertyChanged

  • 你可以使用类型推断,尤其是在使用笨重的类名时有很大帮助。var list = new ObservableCollection<SomeLongTypeName>() 可以节省打字和屏幕空间。

  • 匈牙利命名法让我毛骨悚然;)


我没有理由不直接绑定到列表框,因为我的XAML知识不是很高。我已经通过简单的lstbLeaders.ItemsSource = users编辑了我的项目;根据你的帖子保持UserView类。现在每行都只得到00。 - Nathan
你的XAML长什么样子?使用调试器检查集合值是否设置,或者反序列化是否引入了错误。我在我的答案中添加了一个新的代码片段,适应了你的代码。现在你的XAML将需要绑定到UserLeaderboards类的属性:idusernamescore - Zebi

1

我认为你遗漏了ItemTemplate。试试这个

<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> 

我已经添加了itemTemplate标签,但仍然没有显示任何内容。 - Nathan
你是否也尝试在代码后端设置ItemSource [lstbLeaders.Itemsource = List<T>())?也许字体与背景颜色相同。 :-) - kanchirk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接