.net Maui 未将多对多绑定到选取器中的同一张表

问题描述 投票:0回答:1

我正在创建一个应用程序来注册 Teams 进行体育统计。在本例中,我需要一个视图 (MVVM) 来选择两支球队并分配比赛结果。视图的第一部分(集合视图)按预期工作。我当前的游戏显示在左侧窗格中。右侧是添加新游戏和编辑所选游戏的表单。我的球队显示在选择器中,但问题是在左侧选择游戏后,我的视图没有在选择器中显示所选球队。

这是视图:

    <Grid RowDefinitions="*" ColumnDefinitions="*, *">
        <CollectionView Grid.Row="0" Grid.Column="0" SelectionMode="Single" ItemsSource="{Binding Games}" EmptyView="No items to display" SelectedItem="{Binding SelectedGame}">
            <CollectionView.ItemTemplate>
                <DataTemplate x:DataType="models:Games">
                    <VerticalStackLayout Padding="5">
                        <Label FontSize="14">
                            <Label.Text>
                                <MultiBinding StringFormat="- {0:d}: {1} - {3} ({2}-{4})">
                                    <Binding Path="Date"/>
                                    <Binding Path="Team1.Name" />
                                    <Binding Path="ResultTeam1" />
                                    <Binding Path="Team2.Name" />
                                    <Binding Path="ResultTeam2" />
                                </MultiBinding>
                            </Label.Text>
                        </Label>
                    </VerticalStackLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>

        <ActivityIndicator IsVisible="{Binding IsBusy}" IsRunning="{Binding IsBusy}" HorizontalOptions="Fill" VerticalOptions="Center" Color="{StaticResource Primary}" Grid.RowSpan="1" Grid.ColumnSpan="1" />
            
        <VerticalStackLayout Grid.Row="0" Grid.Column="1" Spacing="10">
            <Picker Title="Team 1" ItemsSource="{Binding Teams}" SelectedItem="{Binding SelectedGame.Team1}" ItemDisplayBinding="{Binding Name}" />
            <Picker Title="Team 2" ItemsSource="{Binding Teams}" SelectedItem="{Binding SelectedGame.Team2}" ItemDisplayBinding="{Binding Name}" />
            <Label Text="Result team 1" />
            <Entry Placeholder="Result team 1" Text="{Binding SelectedGame.ResultTeam1}" />
            <Label Text="Result team 2" />
            <Entry Placeholder="Result team 2" Text="{Binding SelectedGame.ResultTeam2}" />
  
            <HorizontalStackLayout Spacing="10">
                <Button Text="Add" Command="{Binding AddCommand}"/>
                <Button Text="Edit" Command="{Binding EditCommand}"/>
                <Button Text="Deselect" Command="{Binding DeselectCommand}"/>
            </HorizontalStackLayout>
        </VerticalStackLayout>

视图模型:

    public partial class GameViewModel : BaseViewModel
    {
        [ObservableProperty]
        public ObservableCollection<Game> games;

        [ObservableProperty]
        public ObservableCollection<Team> teams;


        [ObservableProperty]
        public Game selectedGame;

        private TeamRepository _teamRepository;
        private GameRepository _gameRepository;

        public GameViewModel(TeamRepository teamRepository, GameRepository gameRepository)
        {
            _teamRepository = teamRepository;
            _gameRepository = gameRepository;

            RefreshGames();
            Teams= new ObservableCollection<Team>(_teamRepository.GetTeams());

            SelectedGame = new Game();
            Title = "Games";
        }

        private void RefreshGames()
        {
            Games= new ObservableCollection<Game>(_gameRepository.GetGames());
        }
...

游戏课

    public class Game
    {
        public int Id { get; set; }
        public int Team1Id { get; set; }
        public int Team2Id { get; set; }
        public Team Team1 { get; set;}
        public Team Team2 { get; set; }

        [DataType(DataType.Date)]
        public DateTime Date{ get; set; } = DateTime.Now;
        public int ResultTeam1 { get; set; }
        public int ResultTeam2 { get; set; }
    }

使用此方法,我成功创建了视图,在选择左侧的项目后,我的数据被检索并显示在选取器中。

此视图的特点是从同一实体中选择两个团队。不知怎的,.net Maui 不计算。

selectedItem 正确返回我的对象,但我的选择器仍为空白。结果条目已正确填写。

我期待在选择器中看到我的 SelectedGame.Teams。

有什么想法吗?

mvvm data-binding maui picker .net-8.0
1个回答
0
投票

根据您提供的代码,我创建了新的演示并尝试实现该功能。

您可以参考以下代码:

GameViewModel.cs

public  class GameViewModel: INotifyPropertyChanged
    {
        public ObservableCollection<Game> Games { get; set; }

        public ObservableCollection<Team> Teams { get; set; }

        private Game _selectedGame;
        public Game SelectedGame
        {
            get { return _selectedGame; }
            set {
                SetProperty(ref _selectedGame, value);
                // update the selectedTeam for the two pickers on the right
                UpdateTheSelectedTeamsForPickker(SelectedGame);
            }
        }

        private Team _selectedTeam1;
        public Team SelectedTeam1
        {
            get { return _selectedTeam1; }
            set { SetProperty(ref _selectedTeam1, value); }
        }

        private Team _selectedTeam2;
        public Team SelectedTeam2
        {
            get { return _selectedTeam2; }
            set { SetProperty(ref _selectedTeam2, value); }
        }

        public GameViewModel()
        {

            RefreshGames();

            Teams = new ObservableCollection<Team>();
            Teams.Add(new Team {  Name ="test_team1"} );
            Teams.Add(new Team {  Name ="test_team2"} );
            Teams.Add(new Team {  Name ="test_team3"} );


            // SelectedGame = new Game();
            SelectedGame = Games[1];

            // update the selectedTeam for the two pickers on the right
            UpdateTheSelectedTeamsForPickker(SelectedGame);
        }

        private void UpdateTheSelectedTeamsForPickker(Game selectedGame) {
            for ( int i=0;i< Teams.Count;i++) {
                Team team = Teams[i];
                if (team.Name == selectedGame.Team1.Name) {
                    SelectedTeam1 = Teams[i];
                }

                if (team.Name == selectedGame.Team2.Name)
                {
                    SelectedTeam2 = Teams[i];
                }
            }
        }

        private void RefreshGames()
        {
           // Games = new ObservableCollection<Game>(_gameRepository.GetGames());
           Games = new ObservableCollection<Game>();
           Games.Add(new Game {  Date = "2024-2-4", Team1 = new Team {  Name = "test_team1" }, Team2 = new Team { Name = "test_team3" }, ResultTeam1 ="win",ResultTeam2 = " failed" });
           Games.Add(new Game {  Date = "2024-2-5", Team1 = new Team {  Name = "test_team2" }, Team2 = new Team { Name = "test_team3" } , ResultTeam1 = "failed", ResultTeam2 = " win" });

        }

        bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
        {
            if (Object.Equals(storage, value))
                return false;
            storage = value;
            OnPropertyChanged(propertyName);
            return true;
        }
        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }

游戏.cs

public  class Game: INotifyPropertyChanged
   {
       public string Date { get; set; }

       private Team _team1;
       public Team Team1
       {
           get { return _team1; }
           set { SetProperty(ref _team1, value); }
       }

       private Team _team2;
       public Team Team2
       {
           get { return _team2; }
           set { SetProperty(ref _team2, value); }
       }

       public string ResultTeam1 { get; set; }

       public string ResultTeam2 { get; set; }


       bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
       {
           if (Object.Equals(storage, value))
               return false;
           storage = value;
           OnPropertyChanged(propertyName);
           return true;
       }
       protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
       {
           PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
       }
       public event PropertyChangedEventHandler PropertyChanged;
   }

Team.cs

public partial class Team: INotifyPropertyChanged
   {
       private string _name;
       public string Name
       {
           get { return _name; }
           set { SetProperty(ref _name, value); }
       }

       bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
       {
           if (Object.Equals(storage, value))
               return false;
           storage = value;
           OnPropertyChanged(propertyName);
           return true;
       }
       protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
       {
           PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
       }
       public event PropertyChangedEventHandler PropertyChanged;
   }

注:

1.如果我们想为Picker设置

SelectedItem
,我们应该从
ItemsSource
中设置一个对象,而不是另一个对象。

因此,我们可以在

GameViewModel.cs
上为右侧的两个选择器添加两个新选定的项目,并在更改
SelectedGame
时更新这两个变量:

    private Team _selectedTeam1;
    public Team SelectedTeam1
    {
        get { return _selectedTeam1; }
        set { SetProperty(ref _selectedTeam1, value); }
    }

    private Team _selectedTeam2;
    public Team SelectedTeam2
    {
        get { return _selectedTeam2; }
        set { SetProperty(ref _selectedTeam2, value); }
    }

我们可以为两个选择器更新上面两个选定的项目,如下所示:

    private void UpdateTheSelectedTeamsForPickker(Game selectedGame) {
        for ( int i=0;i< Teams.Count;i++) {
            Team team = Teams[i];
            if (team.Name == selectedGame.Team1.Name) {
                SelectedTeam1 = Teams[i];
            }

            if (team.Name == selectedGame.Team2.Name)
            {
                SelectedTeam2 = Teams[i];
            }
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.