Observable properties och RelayCommands införda

This commit is contained in:
2025-10-14 21:57:37 +02:00
parent b4d6c6d530
commit 21eb0d5498
17 changed files with 87 additions and 302 deletions

View File

@ -1,29 +0,0 @@
using System.ComponentModel;
namespace Common.Library;
public abstract class CommonBase : INotifyPropertyChanged
{
#region Constructor
protected CommonBase()
{
Init();
}
#endregion
#region Init Method
public virtual void Init()
{
}
#endregion
#region RaisePropertyChanged Method
public event PropertyChangedEventHandler? PropertyChanged;
public virtual void RaisePropertyChanged(string propertyName)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}

View File

@ -1,5 +0,0 @@
namespace Common.Library;
public class EntityBase : CommonBase
{
}

View File

@ -1,14 +0,0 @@
//using GreadyPoang.DataLayer;
namespace Common.Library;
public class ViewModelBase : CommonBase
{
//private readonly LocalDbService _dbService;
//public ViewModelBase(LocalDbService dbService)
//{
// _dbService = dbService;
//}
}

View File

@ -6,19 +6,9 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Compile Remove="BaseClasses\CommonBase.cs" />
<Compile Remove="BaseClasses\EntityBase.cs" />
<Compile Remove="BaseClasses\ViewModelBase.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
</ItemGroup>
<ItemGroup>
<Folder Include="BaseClasses\" />
</ItemGroup>
</Project>

View File

@ -1,5 +1,6 @@
using Common.Library;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using GreadyPoang.EntityLayer;
using System.Collections.ObjectModel;
@ -20,6 +21,7 @@ public partial class ParticipantViewModel : ObservableObject
_sharingService = sharingService;
ParticipantObject = new Participant();
ParticipantList = new ObservableCollection<Participant>();
IsSaveCommandEnabled = true;
}
#endregion
@ -33,6 +35,11 @@ public partial class ParticipantViewModel : ObservableObject
private readonly IMethodSharingService<Participant> _sharingService;
#endregion
[ObservableProperty]
private bool isSaveCommandEnabled;
#region Get Method
public ObservableCollection<Participant> Get()
{
@ -58,7 +65,12 @@ public partial class ParticipantViewModel : ObservableObject
return ParticipantObject;
}
public virtual bool Save()
#endregion
[RelayCommand(CanExecute = nameof(IsSaveCommandEnabled))]
private async Task<bool> Save()
{
if (_Repository == null || ParticipantObject == null)
{
@ -70,8 +82,21 @@ public partial class ParticipantViewModel : ObservableObject
{
ParticipantObject = new Participant();
this.Get();
await Shell.Current.GoToAsync("..");
}
return tmp != -1;
}
#endregion
[RelayCommand]
private void DeleteAsync(Participant pp)
{
Console.WriteLine($"Valt från ViewModel: {pp.FullName}");
if (_Repository == null || pp == null || pp.ParticipantId <= 0)
{
return;
}
var tmpTask = _Repository.Delete(pp);
this.Get();
Shell.Current.GoToAsync("..");
}
}

View File

@ -1,5 +1,6 @@
using Common.Library;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using GreadyPoang.DataLayer;
using GreadyPoang.EntityLayer;
using GreadyPoang.Services;
@ -98,8 +99,8 @@ public partial class RoundRunningViewModel : ObservableObject
return RoundElements;
}
public void StoreAndHandlePoints()
[RelayCommand]
private void StoreAndHandlePointsAsync()
{
var game = _roundsRepo.Get(BuilderObject.GameRoundId).GetAwaiter().GetResult();
var regNr = RoundElements.Count > 0 ? RoundElements.Max(e => e.GameRoundRegNr) + 1 : 1;
@ -147,6 +148,8 @@ public partial class RoundRunningViewModel : ObservableObject
RoundElements.FirstOrDefault(e => e.ParticipantId == col.PlayerId).GameRegPoints = col.PlayerPoints;
}
TriggerRebuild();
Shell.Current.GoToAsync("..").GetAwaiter().GetResult();
}
private int nextPlayerElement()

View File

@ -1,5 +1,6 @@
using Common.Library;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using GreadyPoang.DataLayer;
using GreadyPoang.EntityLayer;
using GreadyPoang.Services;
@ -39,6 +40,7 @@ public partial class RoundStartingViewModel : ObservableObject
private readonly ICombinedRepository _combined;
private readonly IObjectMessageService _objectMessage;
[ObservableProperty]
private Participant selectedItem;
partial void OnSelectedItemChanged(Participant value)
@ -108,6 +110,7 @@ public partial class RoundStartingViewModel : ObservableObject
}
#region Get Method
public ObservableCollection<RoundBuilderGroup> Get()
{
@ -167,7 +170,9 @@ public partial class RoundStartingViewModel : ObservableObject
return GameRoundObject;
}
public virtual bool Save()
[RelayCommand]
public async Task<bool> SaveAsync()
{
if (_roundsRepo == null || GameRoundObject == null)
{
@ -180,11 +185,13 @@ public partial class RoundStartingViewModel : ObservableObject
GameRoundObject = new GameRound();
RoundElements.Clear();
this.Get();
await Shell.Current.GoToAsync("..");
}
return tmp;
}
public void Rensa()
[RelayCommand]
private async Task RensaAsync()
{
foreach (var element in RoundElements)
{
@ -192,22 +199,31 @@ public partial class RoundStartingViewModel : ObservableObject
}
_roundsRepo?.DeleteById(GameRoundObject?.GameRoundId ?? 0);
RoundElements.Clear();
await Shell.Current.GoToAsync("..");
}
public void RoundSelected(RoundBuilderElement element)
[RelayCommand]
public async Task<bool> RoundSelected(RoundBuilderElement element)
{
bool goneOk = false;
var rbGroup = GameRoundList.FirstOrDefault(g => g.GameRoundId == element.GameRoundId);
Debug.WriteLine($"Du valde raden med Runda {element.GameRoundId} och spelare: {element.ParticipantName}");
if (rbGroup != null)
{
_objectMessage.CurrentGroup = rbGroup;
Shell.Current.GoToAsync("//RoundRunningView");
await Shell.Current.GoToAsync("//RoundRunningView");
goneOk = true;
}
return goneOk;
}
public void SelectNewlyAddedParticipant(RoundBuilderElement roundBuilder)
[RelayCommand]
public async Task<bool> SelectNewlyAddedParticipant(RoundBuilderElement roundBuilder)
{
bool goneOk = false;
Debug.WriteLine($"Du valde raden med Runda {roundBuilder.GameRoundId} och spelare: {roundBuilder.ParticipantName}");
goneOk = true;
return goneOk;
}
#endregion

View File

@ -1,58 +0,0 @@
using Common.Library;
using CommunityToolkit.Mvvm.ComponentModel;
using GreadyPoang.EntityLayer;
using GreadyPoang.ViewModelLayer;
using System.Windows.Input;
namespace GreadyPoang.CommandClasses;
public partial class ParticipantViewModelCommands : ParticipantViewModel
{
#region constructors
public ParticipantViewModelCommands() : base()
{
}
public ParticipantViewModelCommands(IRepository<Participant> repo, IMethodSharingService<Participant> sharingService) : base(repo, sharingService)
{
Init();
IsSaveCommandEnabled = true;
}
#endregion
#region Private Variables
[ObservableProperty]
private bool isSaveCommandEnabled;
#endregion
#region Commands
public ICommand SaveCommand { get; private set; }
public ICommand EditCommand { get; private set; }
#endregion
#region Init Method
public void Init()
{
//base.Init();
SaveCommand = new Command(async () => SaveAsync(), () => IsSaveCommandEnabled);
EditCommand = new Command<int>(async (id) => await EditAsync(id), (id) => id > 0);
}
#endregion
protected async Task EditAsync(int id)
{
await Shell.Current.GoToAsync($"{nameof(Views.ParticipantListView)}?id={id}");
}
public async Task<bool> SaveAsync()
{
var ret = base.Save();
if (ret)
{
await Shell.Current.GoToAsync("..");
}
return ret;
}
}

View File

@ -1,51 +0,0 @@
using Common.Library;
using GreadyPoang.DataLayer;
using GreadyPoang.EntityLayer;
using GreadyPoang.Services;
using GreadyPoang.ViewModelLayer;
using System.Windows.Input;
namespace GreadyPoang.CommandClasses;
public class RoundRunningViewModelCommands : RoundRunningViewModel
{
public RoundRunningViewModelCommands() : base()
{
}
public RoundRunningViewModelCommands(
IRepository<GameRound> roundsRepo,
IRepository<GamePoint> pointsRepo,
IMethodSharingService<Participant> sharingService,
ICombinedRepository combined,
IObjectMessageService objectMessage)
: base(roundsRepo,
pointsRepo,
sharingService,
combined,
objectMessage)
{
Init();
}
#region Commands
//public ICommand SaveCommand { get; private set; }
//public ICommand EditCommand { get; private set; }
//public ICommand RensaCommand { get; private set; }
//public ICommand ElementTappedCommand { get; private set; }
//public ICommand ParticipantTappedCommand { get; private set; }
public ICommand StoreAndHandlePointsCommand { get; private set; }
#endregion
public void Init()
{
StoreAndHandlePointsCommand = new Command(async () => StoreAndHandleAsync());
}
private async Task StoreAndHandleAsync()
{
base.StoreAndHandlePoints();
await Shell.Current.GoToAsync("..");
}
}

View File

@ -1,99 +0,0 @@
using Common.Library;
using CommunityToolkit.Mvvm.ComponentModel;
using GreadyPoang.DataLayer;
using GreadyPoang.EntityLayer;
using GreadyPoang.Services;
using GreadyPoang.ViewModelLayer;
using System.Windows.Input;
namespace GreadyPoang.CommandClasses;
public partial class RoundStartingViewModelCommands : RoundStartingViewModel
{
public RoundStartingViewModelCommands() : base()
{
}
public RoundStartingViewModelCommands(
IRepository<GameRound> roundsRepo,
IRepository<GamePoint> pointsRepo,
IMethodSharingService<Participant> sharingService,
ICombinedRepository combined,
IObjectMessageService objectMessage)
: base(roundsRepo,
pointsRepo,
sharingService,
combined,
objectMessage)
{
Init();
IsSaveCommandEnabled = true;
}
#region Private Variables
[ObservableProperty]
private bool isSaveCommandEnabled;
#endregion
#region Commands
public ICommand SaveCommand { get; private set; }
public ICommand EditCommand { get; private set; }
public ICommand RensaCommand { get; private set; }
public ICommand ElementTappedCommand { get; private set; }
public ICommand ParticipantTappedCommand { get; private set; }
#endregion
#region Init Method
public void Init()
{
//base.Init();
SaveCommand = new Command(async () => SaveAsync(), () => IsSaveCommandEnabled);
EditCommand = new Command<int>(async (id) => await EditAsync(id), (id) => id > 0);
RensaCommand = new Command(async () => RensaAsync());
ParticipantTappedCommand = new Command<RoundBuilderElement>(async (selectedParticipant) => SelectNewlyAddedParticipant(selectedParticipant));
ElementTappedCommand = new Command<RoundBuilderElement>((selectedElement) => RoundSelected(selectedElement));
}
private async Task RensaAsync()
{
base.Rensa();
await Shell.Current.GoToAsync("..");
}
#endregion
protected async Task EditAsync(int id)
{
await Shell.Current.GoToAsync($"{nameof(Views.RoundStartingView)}?id={id}");
}
public async Task<bool> SaveAsync()
{
var ret = base.Save();
if (ret)
{
await Shell.Current.GoToAsync("..");
}
return ret;
}
public async Task<bool> RoundSelected(RoundBuilderElement element)
{
bool goneOk = false;
base.RoundSelected(element);
goneOk = true;
return goneOk;
}
public async Task<bool> SelectNewlyAddedParticipant(RoundBuilderElement roundBuilder)
{
bool goneOk = false;
base.SelectNewlyAddedParticipant(roundBuilder);
goneOk = true;
return goneOk;
}
}

View File

@ -1,5 +1,4 @@
using Common.Library;
using GreadyPoang.CommandClasses;
using GreadyPoang.DataLayer;
using GreadyPoang.DataLayer.Database;
using GreadyPoang.EntityLayer;
@ -39,15 +38,15 @@ public static class MauiProgram
});
builder.Services.AddScoped<IRepository<Participant>, ParticipantRepository>();
builder.Services.AddScoped<ParticipantViewModelCommands>();
builder.Services.AddScoped<ParticipantViewModel>();
builder.Services.AddScoped<ParticipantListView>();
builder.Services.AddScoped<IRepository<GameRound>, GameRoundRepository>();
builder.Services.AddScoped<RoundStartingViewModelCommands>();
builder.Services.AddScoped<RoundStartingViewModel>();
builder.Services.AddScoped<RoundStartingView>();
builder.Services.AddScoped<IRepository<GamePoint>, GamePointRepository>();
builder.Services.AddScoped<RoundRunningViewModelCommands>();
builder.Services.AddScoped<RoundRunningViewModel>();
builder.Services.AddScoped<RoundRunningView>();
builder.Services.AddScoped<IMethodSharingService<Participant>, MethodSharingService>();

View File

@ -2,13 +2,15 @@
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:partial="clr-namespace:GreadyPoang.ViewsPartial"
xmlns:vm="clr-namespace:GreadyPoang.CommandClasses"
xmlns:vm="clr-namespace:GreadyPoang.ViewModelLayer;assembly=GreadyPoang.ViewModelLayer"
xmlns:model="clr-namespace:GreadyPoang.EntityLayer;assembly=GreadyPoang.EntityLayer"
x:Class="GreadyPoang.Views.ParticipantListView"
x:DataType="vm:ParticipantViewModelCommands"
x:DataType="vm:ParticipantViewModel"
x:Name="ParticipantListPage"
Title="Deltagar Lista">
<!--xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"-->
<Border Style="{StaticResource Border.Page}" StrokeThickness="4">
<Grid Style="{StaticResource Grid.Page}">
<Grid.RowDefinitions>
@ -22,9 +24,9 @@
ViewDescription="Lägg till deltagare här" />
<Border Stroke="Gold" StrokeThickness="2" BackgroundColor="LemonChiffon" Grid.Row="1">
<VerticalStackLayout Spacing="4" >
<Label Style="{StaticResource Label}"
<!--<Label Style="{StaticResource SubHeadline}"
Text="Deltagare "
FontAttributes="Bold" FontSize="Large"/>
FontAttributes="Bold" />-->
<Grid ColumnDefinitions="Auto,Auto,*" RowDefinitions="Auto,auto,auto,auto"
Padding="10" RowSpacing="8">
<Label Grid.Row="0" Grid.Column="0" Style="{StaticResource Label}"
@ -67,7 +69,6 @@
ItemsUpdatingScrollMode="KeepLastItemInView">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="model:Participant">
<!--Stroke="DarkGray" BackgroundColor="Cornsilk"-->
<Border Margin="8" Padding="12" >
<VerticalStackLayout Spacing="4">
<Label FontAttributes="Bold"
@ -76,7 +77,14 @@
Text="{Binding LastNameFirstName}" />
<HorizontalStackLayout >
<Button Text="Edit" Style="{StaticResource HoverButtonBlueStyle}" CommandParameter="{Binding EditCommand}"/>
<Button Style="{StaticResource HoverButtonRedStyle}" Text="Delete" />
<Button Text="Delete" Style="{StaticResource HoverButtonRedStyle}"
Command="{Binding Source={RelativeSource AncestorType={x:Type vm:ParticipantViewModel}}, Path=DeleteAsyncCommand}"
CommandParameter="{Binding .}" />
<!--Command="{Binding BindingContext.ParticipantTappedCommand, Source={x:Reference Name=ParticipantList}}"
CommandParameter="{Binding .}" />-->
</HorizontalStackLayout>
</VerticalStackLayout>
</Border>

View File

@ -1,16 +1,16 @@
using GreadyPoang.CommandClasses;
using GreadyPoang.ViewModelLayer;
namespace GreadyPoang.Views;
public partial class ParticipantListView : ContentPage
{
public ParticipantListView(ParticipantViewModelCommands viewModel)
public ParticipantListView(ParticipantViewModel viewModel)
{
InitializeComponent();
ViewModel = viewModel;
}
public ParticipantViewModelCommands ViewModel { get; set; }
public ParticipantViewModel ViewModel { get; set; }
public int ParticipantId { get; set; }
protected override void OnAppearing()

View File

@ -3,11 +3,11 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:partial="clr-namespace:GreadyPoang.ViewsPartial"
x:Class="GreadyPoang.Views.RoundRunningView"
xmlns:vm ="clr-namespace:GreadyPoang.CommandClasses"
xmlns:vm ="clr-namespace:GreadyPoang.ViewModelLayer;assembly=GreadyPoang.ViewModelLayer"
xmlns:behaviors="clr-namespace:GreadyPoang.Common;assembly=GreadyPoang.Common"
xmlns:local="clr-namespace:GreadyPoang.EntityLayer;assembly=GreadyPoang.EntityLayer"
xmlns:model="clr-namespace:GreadyPoang.EntityLayer;assembly=GreadyPoang.EntityLayer"
x:DataType="vm:RoundRunningViewModelCommands"
x:DataType="vm:RoundRunningViewModel"
Title="RoundRunningView">
<Border Style="{StaticResource Border.Page}" StrokeThickness="4">
@ -78,13 +78,13 @@
<Entry.Behaviors>
<behaviors:DigitsOnlyBehavior/>
<behaviors:EventToCommandBehavior EventName="Completed"
Command="{Binding StoreAndHandlePointsCommand}" />
Command="{Binding StoreAndHandlePointsAsyncCommand}" />
</Entry.Behaviors>
</Entry>
</Grid>
<Button Text="Register Points"
Style="{StaticResource HoverButtonRedStyle}"
Command="{Binding StoreAndHandlePointsCommand}"/>
Command="{Binding StoreAndHandlePointsAsyncCommand}"/>
</HorizontalStackLayout>
</Border>
<ScrollView Grid.Row="4" Orientation="Horizontal">

View File

@ -1,11 +1,11 @@
using GreadyPoang.CommandClasses;
using GreadyPoang.EntityLayer;
using GreadyPoang.ViewModelLayer;
namespace GreadyPoang.Views;
public partial class RoundRunningView : ContentPage
{
public RoundRunningView(RoundRunningViewModelCommands viewModel)
public RoundRunningView(RoundRunningViewModel viewModel)
{
InitializeComponent();
ViewModel = viewModel;
@ -29,7 +29,7 @@ public partial class RoundRunningView : ContentPage
//protected override
public RoundRunningViewModelCommands ViewModel { get; set; }
public RoundRunningViewModel ViewModel { get; set; }
private void BuildScoreGrid(IEnumerable<PlayerColumn> columns)

View File

@ -3,10 +3,10 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:partial="clr-namespace:GreadyPoang.ViewsPartial"
x:Class="GreadyPoang.Views.RoundStartingView"
xmlns:vm="clr-namespace:GreadyPoang.CommandClasses"
xmlns:vm="clr-namespace:GreadyPoang.ViewModelLayer;assembly=GreadyPoang.ViewModelLayer"
xmlns:local="clr-namespace:GreadyPoang.EntityLayer;assembly=GreadyPoang.EntityLayer"
xmlns:model="clr-namespace:GreadyPoang.EntityLayer;assembly=GreadyPoang.EntityLayer"
x:DataType="vm:RoundStartingViewModelCommands"
x:DataType="vm:RoundStartingViewModel"
x:Name="GameRoundStartingPage"
Title="Starta ny Runda">
@ -64,7 +64,7 @@
>
<Border.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding BindingContext.ParticipantTappedCommand, Source={x:Reference Name=ParticipantList}}"
Command="{Binding BindingContext.SelectNewlyAddedParticipantCommand, Source={x:Reference Name=ParticipantList}}"
CommandParameter="{Binding .}" />
</Border.GestureRecognizers>
<Border Margin="1" Padding="2" StrokeThickness="3" >
@ -129,7 +129,7 @@
Style="{StaticResource StatusBorderStyle}" >
<Border.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding Path=BindingContext.ElementTappedCommand,Source={x:Reference OuterList}}"
Command="{Binding Path=BindingContext.RoundSelectedCommand ,Source={x:Reference OuterList}}"
CommandParameter="{Binding .}" />
</Border.GestureRecognizers>

View File

@ -1,4 +1,4 @@
using GreadyPoang.CommandClasses;
using GreadyPoang.ViewModelLayer;
namespace GreadyPoang.Views;
@ -6,12 +6,12 @@ public partial class RoundStartingView : ContentPage
{
public RoundStartingView(RoundStartingViewModelCommands viewModel)
public RoundStartingView(RoundStartingViewModel viewModel)
{
InitializeComponent();
ViewModel = viewModel;
}
public RoundStartingViewModelCommands ViewModel { get; set; }
public RoundStartingViewModel ViewModel { get; set; }
public int GameRoundId { get; set; }