Я определил объект Player следующим образом:
public class Player
{
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
public string PlayerName { get; set; }
public DateTime JoinDate { get; set; }
public int TotalMatchesWon { get; set; }
public int TotalMatchesLost { get; set; }
public float WinPercentage { get; set; }
public int Rank { get; set; }
}
Я храню проигрыватели в базе данных SQLite. Я реализую следующие страницы для приложения android в Xamarin:
Учетная запись -> Подробная информация о реестре -> Редактировать плеер
Страницы имеют следующие функциональные возможности:
Ростер: 1. Roster.xmal содержит ListView of Players (Список), заполняемый из следующей функции в Roster.xmal.cs.
protected override async void OnAppearing()
{
base.OnAppearing();
listView.ItemsSource = await App.Database.GetPlayersAsync();
}
Добавить нового игрока в реестр. Это вызывает страницу редактирования проигрывателя с пустыми полями, используя следующий код в файле Roster.xmal.cs.
async void OnPlayerAddedClicked(object send, EventArgs e)
{
await Navigation.PushAsync(new RosterEntryPage
{
BindingContext = new Player()
});
}
Вы можете выбрать игрока из списка. Это берет SelectedItem и отправляет Player в PlayerDetailPage (также в Roster.xmal.cs)
async void OnListViewItemSelected(object sender, SelectedItemChangedEventArgs e)
{
if (e.SelectedItem != null)
{
await Navigation.PushAsync(new PlayerDetailPage
{
BindingContext = e.SelectedItem as Player
});
}
}
Сведения о ростере: 1. Отображает объект Player, который был передается ему из функции OnListViewItemSelected (). На странице нет кода, который бы указывал на наличие проигрывателя, но я могу ссылаться на поля проигрывателя в файле RosterDetails.xmal (поэтому я и называю его «косвенным» объектом), например:
<Label Grid.Column="2"
Text="{Binding PlayerName}"
FontSize="18"
FontAttributes="Bold" />
Пользователь может нажать на кнопку, чтобы отредактировать плеер. Это снова вызывает RosterEntryPage (например, для добавления нового игрока), но на этот раз он пропускает игрока, который у него уже есть. Это та часть, которая сломана. Если я вызываю страницу редактирования напрямую из Roster.xmal, я могу предварительно заполнить все пустые поля (но это только PlayerName) и обновить запись SQLite. Я хотел бы передать косвенный объект, используемый RosterDetail.xmal, на страницу редактирования, чтобы сделать то же самое.
Вот RosterDetail.xmal.cs:
public partial class PlayerDetailPage : ContentPage
{
public PlayerDetailPage()
{
InitializeComponent();
}
async void OnEditPlayerButtonClicked(object send, EventArgs e)
{
await floatingButtonEdit.ScaleTo(1.5, 500);
await floatingButtonEdit.ScaleTo(0, 500, Easing.SpringOut);
await Navigation.PushAsync(new RosterEntryPage
{
BindingContext = new Player()
});
}
}
Я знаю, что проблема в BindingContext = new Player (), но я понятия не имею, чем заменить его. Я пробовал разные вещи, такие как BindingContext = e.Player, но это выдает ошибку, что e.Player недействителен. Я также попытался изменить параметры функции, чтобы они соответствовали OnListViewItemSelected (), чтобы он был OnEditPlayerButtonClicked (отправитель объекта, SelectedItemChangedEventArgs e), но это приводит к тому, что приложение обрабатывает sh.
EDIT Здесь это xmal для страницы, где вы вводите данные, чтобы добавить нового игрока или отредактировать существующий.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Foosball.RosterEntryPage"
Title="Roster Entry">
<StackLayout Margin="20">
<Editor Placeholder="Enter player name"
Text="{Binding PlayerName}"
HeightRequest="50" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Text="Save"
Clicked="OnRosterEntrySaveButtonClicked"
Grid.Row="1" />
<Button Text="Delete"
Clicked="OnRosterEntryDeleteButtonClicked"
Grid.Row="1"
Grid.Column="1"/>
</Grid>
</StackLayout>
</ContentPage>
Вот соответствующий файл .cs
public partial class RosterEntryPage : ContentPage
{
public RosterEntryPage()
{
InitializeComponent();
}
public RosterEntryPage(Player newPlayer)
{
InitializeComponent();
}
async void OnRosterEntrySaveButtonClicked(object sender, EventArgs e)
{
var player = (Player)BindingContext;
player.JoinDate = DateTime.UtcNow;
await App.Database.SavePlayerAsync(player);
await Navigation.PopAsync();
}
async void OnRosterEntryDeleteButtonClicked(object sender, EventArgs e)
{
var player = (Player)BindingContext;
await App.Database.DeletePlayerAsync(player);
await Navigation.PopAsync();
}
}