C# 显示api调用TextBlock(MVVM)中的单个值

C# 显示api调用TextBlock(MVVM)中的单个值,c#,wpf,mvvm,C#,Wpf,Mvvm,我已经被困在这几个小时了。我正在为我正在构建的应用程序使用IGDB api。所以,我正在尝试获取列表框,我必须显示游戏标题、封面和开发者。我已经设法让所有的开发者都出现在列表中,没有问题,但是当我只想在列表中显示一个开发者时,主要的问题就出现了,该列表显示了所有涉及的公司以及开发人员,因为API返回了一个涉及公司的数组,在这些涉及公司中,开发人员主体返回一个布尔值,以说明哪一个是开发人员。我可以在我的脑海中看到,如果开发者是真的,那么就向开发者展示,并删除其他相关公司。以下是我运行查询时显示的图

我已经被困在这几个小时了。我正在为我正在构建的应用程序使用IGDB api。所以,我正在尝试获取列表框,我必须显示游戏标题、封面和开发者。我已经设法让所有的开发者都出现在列表中,没有问题,但是当我只想在列表中显示一个开发者时,主要的问题就出现了,该列表显示了所有涉及的公司以及开发人员,因为API返回了一个涉及公司的数组,在这些涉及公司中,开发人员主体返回一个布尔值,以说明哪一个是开发人员。我可以在我的脑海中看到,如果开发者是真的,那么就向开发者展示,并删除其他相关公司。以下是我运行查询时显示的图像:

我用红色勾勒了它的轮廓。从这个列表中,我需要的是Bungie,因为他们是开发者。因此,在我的视图中,有一个列表框和一个嵌套在其中的列表视图:

BrowseGamesView

<ListBox ItemsSource="{Binding Games}"
             Width="390"
             Height="500"
             Grid.Row="4">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <Border Grid.Column="0"
                            Grid.Row="0"
                            Grid.RowSpan="2"
                            Margin="0 0 10 0">
                        <Image Source="{Binding cover.image_id, Converter={StaticResource stringToImage}}"
                               Stretch="Fill"
                               Height="70"
                               Width="60"/>
                    </Border>
                    <TextBlock Text="{Binding name}"
                               FontWeight="Bold"
                               Grid.Column="1"
                               Grid.Row="0"/>
                    <ListView Grid.Column="1"
                              Grid.Row="1"
                              ItemsSource="{Binding involved_companies}">
                        <ListView.ItemTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding company.name}"/>
                            </DataTemplate>
                        </ListView.ItemTemplate>
                    </ListView>
                </Grid>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

在我的ViewModel中,我有一个进行查询的方法,还保存了ObservableCollection(游戏)

BrowseGamesViewModel

public ObservableCollection<Game> Games { get; set; }

public async void MakeQuery()
        {
            var games = await IGDBHelper.GetGames(Query);

            Games.Clear();
            foreach(var game in games)
            {
                Games.Add(game);
            }
        }
公共可观测集合游戏{get;set;}
公共异步void MakeQuery()
{
var games=await-IGDBHelper.GetGames(查询);
游戏。清除();
foreach(游戏中的var游戏)
{
Games.Add(游戏);
}
}
在我的助手课上,我得到了游戏

IGDBHelper

public static async Task<List<Game>> GetGames(string query)
        {
            List<Game> games = new List<Game>();

            string myJson = "search \"{0}\"; fields name, cover.url, cover.image_id, involved_companies.developer, involved_companies.company.name; limit 500;";

            using (HttpClient client = new HttpClient())
            {
                client.DefaultRequestHeaders.Add("user-key", "key hidden");

                var response = await client.PostAsync(BASE_URL_GAMES, new StringContent(string.Format(myJson, query), Encoding.UTF8, "application/json"));

                var responseString = await response.Content.ReadAsStringAsync();

                games = JsonConvert.DeserializeObject<List<Game>>(responseString);
            }

            return games;
        }
公共静态异步任务GetGames(字符串查询)
{
列表游戏=新列表();
string myJson=“search\”{0}\”字段名称,cover.url,cover.image\u id,included\u companys.developer,included\u companys.company.name;limit 500;”;
使用(HttpClient=new HttpClient())
{
client.DefaultRequestHeaders.Add(“用户密钥”、“密钥隐藏”);
var response=wait client.PostAsync(BASE_URL_GAMES,newstringcontent(string.Format(myJson,query),Encoding.UTF8,“application/json”);
var responseString=await response.Content.ReadAsStringAsync();
games=JsonConvert.DeserializeObject(responseString);
}
返回游戏;
}
所有模型都是Json的具体类

public class Game
    {
        public int id { get; set; }
        public Cover cover { get; set; }
        public List<InvolvedCompany> involved_companies { get; set; }
        public string name { get; set; }
    }


public class InvolvedCompany
    {
        public int id { get; set; }
        public Company company { get; set; }
        public bool developer { get; set; }
    }

public class Company
    {
        public int id { get; set; }
        public string name { get; set; }
    }

public class Cover
{
    public int id { get; set; }
    public string image_id { get; set; }
    public string url { get; set; }
}
公共类游戏
{
公共int id{get;set;}
公共封面{get;set;}
涉及的公共列表{get;set;}
公共字符串名称{get;set;}
}
涉及的公共类公司
{
公共int id{get;set;}
上市公司{get;set;}
公共bool开发人员{get;set;}
}
公营公司
{
公共int id{get;set;}
公共字符串名称{get;set;}
}
公共类封面
{
公共int id{get;set;}
公共字符串图像\u id{get;set;}
公共字符串url{get;set;}
}

因此,重申一下,我需要以某种方式显示开发者的名字,从列表中删除其他相关公司。从转换器到在converter类中尝试它,我已经尝试了很多方法,每次我都会得到null异常。

首先,我建议用PascalCase命名您的属性。 现在针对您的问题,我建议按开发商属性筛选公司,并在将其添加到列表之前为游戏指定一个新的涉及公司列表

foreach(var game in games)
  {
     game.involved_companies = game.involved_companies.Where(e => e.developer == true).Tolist();
     Games.Add(game);
  }

未经测试,但我相信这应该会起作用。

我将向
游戏
类添加一个新的只读属性:

public List<InvolvedCompany> DeveloperCompanies 
{ 
    get 
    { 
        return involved_companies.Where(c => c.developer == true).ToList();  
    } 
}
公共列表开发公司
{ 
得到
{ 
返回涉及的公司。其中(c=>c.developer==true)。ToList();
} 
}
然后可以将此新属性绑定到ListView:

<ListView Grid.Column="1"
          Grid.Row="1"
          ItemsSource="{Binding DeveloperCompanies}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding company.name}"/>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

这样,您将只显示开发公司,但如果您需要将其用于其他目的,您也将保留所有相关公司的信息


我还建议你使用PascalCase作为班级的公共成员。因此,例如,
相关公司
将成为
相关公司

谢谢。它工作得非常完美,现在对我来说更有意义。由于某种原因,当我使用PascalCase时,我无法正确地对Json进行反序列化。你知道为什么会这样吗?例如,如果我使用Cover.cs中的属性,例如image_id,并将其更改为ImageId,则即使在代码中更改了其所有引用,该属性也不再工作。在滚动结果时,代码也会抛出一个null异常。将其包装成try/catch会更好吗?这是因为您从中获取此信息的web服务正在使用属性名snake_case(image_id、涉及的公司等)序列化为Json。如果你不能改变这一点,那么就像你一样使用snake_案例。很好。它们必须匹配才能反序列化到具体的类。例外情况如何?除了try/catch语句之外,我似乎不知道如何解决这个问题。我只是在涉及的公司中添加了addnull检查,如果是,则返回一个新列表。再次感谢您的帮助:)这是可行的,它将抛出一个空异常,但我可以解决这个问题。