我正在创建一个应用程序来注册 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。
有什么想法吗?
根据您提供的代码,我创建了新的演示并尝试实现该功能。
您可以参考以下代码:
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];
}
}
}