проверка формы net maui
Все еще изучаю. Я пытаюсь выполнить проверку модели с помощью CommunityToolkit.Mvvm, и я застрял в стилях (минимум там).
Вот что я пробовал:
Модель:
public abstract partial class BaseModel : ObservableObject, IDataErrorInfo
{
private Dictionary<string, string> validationErrors = new Dictionary<string, string>();
private bool isValid = false;
protected Dictionary<string, string> ValidationErrors
{
get => validationErrors;
private set => SetProperty(ref validationErrors, value);
}
protected bool IsValid
{
get => isValid;
private set => SetProperty(ref isValid, value);
}
[RelayCommand]
protected void Validate()
{
var context = new ValidationContext(this);
var errors = new List<ValidationResult>();
isValid = Validator.TryValidateObject(this, context, errors, true);
foreach (var error in errors)
{
var columnName = error.MemberNames.First();
if(!validationErrors.ContainsKey(columnName))
validationErrors.Add(columnName, error.ErrorMessage);
}
}
// check for general model error
public string Error { get; private set; } = null;
// check for property errors
public string this[string columnName]
{
get
{
Validate();
return validationErrors[columnName];
}
}
}
public class PlayerModel : BaseModel
{
public int Id { get; set; }
[Required]
[StringLength(255)]
public string Name { get; set; }
[StringLength(4096)]
public string LocalImageLink { get; set; }
[Required]
[StringLength(4096)]
public string WebImageLink { get; set; }
[Required]
[StringLength(255)]
public string Club { get; set; }
[Required]
[StringLength(32)]
public string Birthday { get; set; }
[Required]
[StringLength(255)]
public string BirthPlace { get; set; }
[Required]
[Range(0, 100)]
public int Weight { get; set; }
[Required]
[Range(0, 2.5)]
public double Height { get; set; }
[Required]
public string Description { get; set; }
public string PositionName { get; set; }
[Required]
[Range(1, 7)]
public int PositionId { get; set; }
public PlayerModel()
{
}
public PlayerModel(int id, string name, string localImageLink, string webImageLink, string club, string birthday, string birthPlace, int weight, double height, string description, string positionName, int positionId)
{
Id = id;
Name = name;
LocalImageLink = localImageLink;
WebImageLink = webImageLink;
Club = club;
Birthday = birthday;
BirthPlace = birthPlace;
Weight = weight;
Height = height;
Description = description;
PositionName = positionName;
PositionId = positionId;
}
public PlayerModel(int id, string name, string localImageLink, string webImageLink, string club, string birthday, string birthPlace, int weight, double height, string description, PositionModel position)
{
Id = id;
Name = name;
LocalImageLink = localImageLink;
WebImageLink = webImageLink;
Club = club;
Birthday = birthday;
BirthPlace = birthPlace;
Weight = weight;
Height = height;
Description = description;
PositionName = position.Name;
PositionId = position.Id;
}
public PlayerModel(PlayerEntity player)
{
Id = player.Id;
Name = player.Name;
LocalImageLink = player.LocalImageLink;
WebImageLink = player.WebImageLink;
Club = player.Club;
Birthday = player.Birthday;
BirthPlace = player.BirthPlace;
Weight = player.Weight;
Height = player.Height;
Description = player.Description;
PositionName = player.Position.Name;
PositionId = player.Position.Id;
}
public PlayerEntity ToEntity()
{
return new PlayerEntity
{
Id = Id,
Name = Name,
LocalImageLink = LocalImageLink,
WebImageLink = WebImageLink,
Club = Club,
Birthday = Birthday,
BirthPlace = BirthPlace,
Weight = Weight,
Height = Height,
Description = Description,
Position = new PositionEntity
{
Id = PositionId,
Name = PositionName
}
};
}
public void ToEntity(PlayerEntity player)
{
player.Id = Id;
player.Name = Name;
player.LocalImageLink = LocalImageLink;
player.WebImageLink = WebImageLink;
player.Club = Club;
player.Birthday = Birthday;
player.BirthPlace = BirthPlace;
player.Weight = Weight;
player.Height = Height;
player.Description = Description;
player.Position.Id = PositionId;
player.Position.Name = PositionName;
}
}
Вид:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiUI.Pages.AddOrUpdatePlayer"
xmlns:local="clr-namespace:Backend.Models;assembly=Backend.Models"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit">
<ContentPage.BindingContext>
<local:PlayerModel />
</ContentPage.BindingContext>
<ContentPage.ToolbarItems>
<ToolbarItem IconImageSource="save.svg" Clicked="OnSaveClick"/>
</ContentPage.ToolbarItems>
<ScrollView Margin="10">
<VerticalStackLayout>
<VerticalStackLayout>
<Label Text="Name" />
<Entry x:Name="name" Text="{Binding Name, Mode=TwoWay}"
ClearButtonVisibility="WhileEditing">
<Entry.Behaviors>
<toolkit:EventToCommandBehavior
EventName="TextChanged"
Command="{Binding Validate}" />
</Entry.Behaviors>
</Entry>
</VerticalStackLayout>
<VerticalStackLayout Margin="0,10">
<Label Text="Position" />
<Picker x:Name="position" Title="Select..."
ItemDisplayBinding="{Binding Name}"
SelectedItem="{Binding PositionId, Mode=TwoWay}" />
</VerticalStackLayout>
<VerticalStackLayout Margin="0,10">
<Label Text="Club" />
<Entry x:Name="club" Text="{Binding Club, Mode=TwoWay}"
ClearButtonVisibility="WhileEditing" />
</VerticalStackLayout>
<VerticalStackLayout Margin="0,10">
<Label Text="Birthday" />
<DatePicker x:Name="birthday" Date="{Binding Birthday, Mode=TwoWay}" />
</VerticalStackLayout>
<VerticalStackLayout Margin="0,10">
<Label Text="Birth place" />
<Entry x:Name="birthplace" Text="{Binding BirthPlace, Mode=TwoWay}"
ClearButtonVisibility="WhileEditing" />
</VerticalStackLayout>
<VerticalStackLayout Margin="0,10">
<Label Text="Weight" />
<Entry x:Name="weight" Text="{Binding Weight, Mode=TwoWay}"
ClearButtonVisibility="WhileEditing" Keyboard="Numeric"/>
</VerticalStackLayout>
<VerticalStackLayout Margin="0,10">
<Label Text="Height" />
<Entry x:Name="height" Text="{Binding Height, Mode=TwoWay}"
ClearButtonVisibility="WhileEditing" Keyboard="Numeric"/>
</VerticalStackLayout>
<VerticalStackLayout Margin="0,10">
<Label Text="Image link" />
<Entry x:Name="webImageLink" Text="{Binding WebImageLink, Mode=TwoWay}"
ClearButtonVisibility="WhileEditing"/>
</VerticalStackLayout>
<VerticalStackLayout Margin="0,10">
<Label Text="Description" />
<Editor x:Name="description" Text="{Binding Description, Mode=TwoWay}"
AutoSize="TextChanges"/>
</VerticalStackLayout>
</VerticalStackLayout>
</ScrollView>
</ContentPage>
Посмотреть код позади:
[QueryProperty(nameof(Player), "player")]
public partial class AddOrUpdatePlayer : ContentPage
{
private PlayerModel player;
public PlayerModel Player
{
get => player;
set
{
player = value;
OnPropertyChanged();
}
}
private readonly IPositionClient positionClient;
private readonly IPlayerClient playerClient;
private delegate Task Action();
private Action asyncAction;
public AddOrUpdatePlayer(IPositionClient positionClient, IPlayerClient playerClient)
{
InitializeComponent();
SetUpControls();
SetTitle();
SetActionPointer();
this.positionClient = positionClient;
this.playerClient = playerClient;
}
protected async override void OnAppearing()
{
BindingContext = player;
await SetUpPositionPicker();
}
private void SetUpControls()
{
birthday.MinimumDate = new DateTime(1900, 1, 1);
birthday.MaximumDate = DateTime.Now.Date;
}
private async Task SetUpPositionPicker()
{
position.ItemsSource = await this.positionClient.GetAllAsync();
}
private void SetTitle()
{
Title = this.player is null ?
"Add new player" :
$"Update {player.Name}";
}
private void SetActionPointer()
{
asyncAction = this.player is null ?
AddNewPlayer :
UpdatePlayer;
}
private async Task AddNewPlayer()
{
var player = BindingContext as PlayerModel;
await playerClient.CreateAsync(player);
await Shell.Current.GoToAsync(PageRoutes.HomePage, true);
}
private async Task UpdatePlayer()
{ }
private async void OnSaveClick(object sender, EventArgs e)
{
await asyncAction();
}
}
Глобальный стиль:
<?xml version="1.0" encoding="UTF-8" ?>
<?xaml-comp compile="true" ?>
<ResourceDictionary
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:mct="http://schemas.microsoft.com/dotnet/2022/maui/toolkit">
<Entry.Style>
<OnPlatform x:TypeArguments="Style">
<On Platform="iOS, Android" Value="{StaticResource EntryStyle}" />
<On Platform="WinUI" Value="{StaticResource WinUIEntryStyle}" />
</OnPlatform>
</Entry.Style>
<Entry.Behaviors>
<mct:EventToCommandBehavior
EventName="TextChanged"
Command="{Binding Validate}" />
</Entry.Behaviors>
<Entry.Triggers>
<DataTrigger
TargetType="Entry"
Binding="{Binding UserName.IsValid}"
Value="False">
<Setter Property="BackgroundColor" Value="{StaticResource ErrorColor}" />
</DataTrigger>
</Entry.Triggers>
</ResourceDictionary>
Мне нужно изменить свойство Entry.Triggers DataTrigger Binding, чтобы адаптироваться к моему решению, если это возможно. Моя другая проблема заключается в том, что при нажатии кнопки для сохранения BindingContext имеет значение null, данные не привязываются к модели в функции AddNewPlayer().