0

我正在尝试创建一个小型应用程序,我可以在其中为即将到来的欧洲足球锦标赛制作一个小球。

为此,我当然需要添加匹配项。

我希望有 3 个组合框,其中第一个由它的匹配类型设置(Poule A、Poule B 等)。设置该组合框后,我希望接下来的两个组合框仅显示这些 poules 中的团队。

我相信这可以使用转换器来完成,但我似乎无法让它工作..还是有更好的方法?

当前代码:

<ComboBox ItemsSource="{Binding MatchTypes}"
                        DisplayMemberPath="TypeName"
                        Grid.Row="1" />

<ComboBox ItemsSource="{Binding Teams}"
                        DisplayMemberPath="TeamName"
                        Grid.Column="1"
                        Grid.Row="1" />

<ComboBox ItemsSource="{Binding Teams}"
                        DisplayMemberPath="TeamName"
                        Grid.Column="2"
                        Grid.Row="1" />

有没有一种简单的方法(linq?)来查询最后两个组合框,只查询在第一个组合框中选择的 poule 中的团队?

如果可能的话,我更喜欢将其保留在视图模型之外并使用转换器或类似的东西。

4

1 回答 1

2

就个人而言,我会将其保留在 viewmodel 代码中。我做了类似的事情,所以在这里,映射到你正在做的事情:

  • 我的视图模型中有一个预先填充的项目列表。这将是 MatchTypes。

  • 我将拥有另一个名为 CurrentMatchType 的属性,在设置时使用 INotifyPropertyChanged。

  • 当设置 CurrentMatchType 的值时,它将调用数据源并填充视图模型上的其他两个列表。我们还有 2 个变量,称为 PouleA 和 PouleB,代表最终的团队选择。我们将调用您刚刚从服务器 TeamsA 和 TeamsB 获取的列表。两个列表的数据相同,但我会将数据源结果设置为内部值,然后将 TeamsA 设置为除 PouleB 中选择的团队之外的所有团队的列表,并将 TeamsB 的列表设置为除 PouleB 之外的所有团队的列表PouleA中的那些。这样一来,一个团队无法单独匹配。

  • 我忘记的最后一件事:在 PouleA 和 PouleB 的设置器上,您将运行与上面相同的代码来过滤可用的团队,因此也排除了对面的团队。由于 INPC 连接到所有内容,您的组合框都会自动更改。

  • 当我从数据源中抓取数据时,我会公开一个属性以让 BusyIndi​​cator 接管屏幕,因此在完成抓取数据之前不能触摸任何内容。

我认为尝试使用转换器来处理此类事情会增加不必要的挫败感。如果您不想将它添加到您的视图模型中,因为您在不同的地方重复使用它,那么没有什么能阻止您创建一个将旧视图模型作为属性公开的新视图模型。

伪代码

using System;

/* In your model... */

public sealed class MatchType
{
    public string Name { get; internal set; }
    public string Description { get; internal set; }
    public int ID { get; internal set; }
}

public sealed class Team
{
    public string Name { get; set; }
    public MatchType MatchType { get; set; }
    public int? MatchTypeID { get; set; }
    public int ID { get; set; }
}

/* In your viewmodel... */

public sealed class TeamSelection
{

    // These two should be INotifyPropertyChanged, shortened for this example.
    public MatchType[] MatchTypes { get; private set; }
    public Team[] TeamsA { get; private set; }
    public Team[] TeamsB { get; private set; }

    private Team[] teams = null;
    MatchType matchType = null;
    public MatchType SelectedMatchType {
        get { return matchType; }
        set
        {
            if (value != null)
                matchType = value;
            else if (MatchTypes != null && MatchTypes.Length > 0)
                matchType = MatchTypes[0];
            else
                return;
            PropertyHasChanged(() => SelectedMatchType);
            PopulateTeams();
        }
    }

    Team teamA;
    Team teamB;

    public Team SelectedTeamA 
    {
        get { return teamA; }
        set
        {
            if (teamA.ID == teamB.ID)
                // Alternatively, set a flag and stop execution.
                throw new InvalidOperationException("The same team cannot be selected.");
            teamA = value;
            PopulateTeams();
            PropertyHasChanged(() => SelectedTeamA);
        }
    }

    public Team SelectedTeamB 
    {
        get { return teamB; }
        set
        {
            if (teamA.ID == teamB.ID)
                // Alternatively, set a flag and stop execution.
                throw new InvalidOperationException("The same team cannot be selected.");
            teamB = value;
            PopulateTeams();
            PropertyHasChanged(() => SelectedTeamB);
        }
    }

    /// <summary>
    /// This can be done on your model, or what I do is pass it to 
    /// an intermediary class, then that sets the busy status to
    /// a BusyIndicator set as the visual root of the application.
    /// </summary>
    public bool IsBusy { get; private set; }
    public string IsBusyDoingWhat { get; private set; }

    public TeamSelection()
    {
        // Call out to DB for the match types, setting busy status
        var wcf = new WcfService();
        wcf.GetMatchTypes(response => 
        {
            wcf.GetMatchTypesForTeam(MatchType, response2 =>
            {
                teams = response.Value.ToArray();
                MatchTypes = response2.Value.ToArray();
                MatchType = MatchTypes[0];
                PopulateTeams();
            });
        });
    }

    void PopulateTeams()
    {
        if (MatchType == null)
            return;
        var op = teams.Where(t => t.MatchTypeID == MatchType.ID);
        if (SelectedTeamA != null)
            TeamsB = op.Where(t => t.ID != SelectedTeamA.ID).OrderBy(t => t.Name);
        else
            TeamsB = op.OrderBy(t => t.Name);
        if (SelectedTeamB != null)
            TeamsA = op.Where(t => t.ID != SelectedTeamB.ID).OrderBy(t => t.Name);
        else
            TeamsA = op.OrderBy(t => t.Name);
    }

}
于 2012-05-06T13:20:29.527 回答