Nu fungerar RoundRunningView med minimal codeBehind

This commit is contained in:
2025-10-22 10:42:39 +02:00
parent ecd3e90dbf
commit 26ff51169f
13 changed files with 374 additions and 116 deletions

View File

@ -0,0 +1,12 @@
using System.Globalization;
namespace GreadyPoang.Common;
public class HeaderColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) =>
(bool)value ? Colors.DarkGray : Colors.Yellow;
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) =>
throw new NotImplementedException();
}

View File

@ -0,0 +1,35 @@
using System.Windows.Input;
namespace GreadyPoang.Common;
public class LoadedBehavior
{
public static readonly BindableProperty CommandProperty =
BindableProperty.CreateAttached(
"Command",
typeof(ICommand),
typeof(LoadedBehavior),
null,
propertyChanged: OnCommandChanged);
public static ICommand GetCommand(BindableObject view) =>
(ICommand)view.GetValue(CommandProperty);
public static void SetCommand(BindableObject view, ICommand value) =>
view.SetValue(CommandProperty, value);
private static void OnCommandChanged(BindableObject bindable, object oldValue, object newValue)
{
if (bindable is VisualElement element && newValue is ICommand command)
{
element.Loaded += (s, e) =>
{
if (command.CanExecute(null))
{
command.Execute(null);
}
};
}
}
}

View File

@ -0,0 +1,7 @@
namespace GreadyPoang.EntityLayer;
public class ScoreCell
{
public string Text { get; set; }
public bool IsHeader { get; set; }
}

View File

@ -0,0 +1,9 @@
using System.Collections.ObjectModel;
namespace GreadyPoang.EntityLayer;
public class ScoreColumn
{
public string PlayerName { get; set; }
public ObservableCollection<ScoreCell> Cells { get; set; } = new();
}

View File

@ -7,6 +7,7 @@ using GreadyPoang.EntityLayer;
using GreadyPoang.Services;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Windows.Input;
namespace GreadyPoang.ViewModelLayer;
@ -14,6 +15,7 @@ public partial class RoundRunningViewModel : ObservableObject
{
public event EventHandler RebuildRequested;
public ICommand OnLoadedCommand { get; }
public RoundRunningViewModel() : base()
{
@ -41,6 +43,8 @@ public partial class RoundRunningViewModel : ObservableObject
BuilderObject = new();
_popupEvent.InfoPopupCloseRequested += infoPopupViewModel_ClosePopupRequested;
PopupVisad = false;
OnLoadedCommand = new AsyncRelayCommand(OnLoadedAsync, () => true);
}
private readonly IRepository<GameRound>? _roundsRepo;
@ -57,19 +61,20 @@ public partial class RoundRunningViewModel : ObservableObject
private Collection<PlayerColumn> playerColumns;
[ObservableProperty]
private RoundBuilderElement builderObject;
public ObservableCollection<ScoreColumn> ScoreColumns { get; } = new ObservableCollection<ScoreColumn>();
private string _activePopupId;
public bool PopupVisad { get; set; }
public void TriggerRebuild()
private async Task OnLoadedAsync()
{
// Trigga eventet
RebuildRequested?.Invoke(this, EventArgs.Empty);
await Get();
}
public void Get()
public async Task Get()
{
if (_objectMessage.CurrentGroup != null)
@ -102,10 +107,13 @@ public partial class RoundRunningViewModel : ObservableObject
{
RoundElements.FirstOrDefault(e => e.ParticipantId == col.PlayerId).GameRegPoints = col.PlayerPoints;
}
TriggerRebuild();
//TriggerRebuild();
BuildScore(playerColumns);
}
}
[RelayCommand]
private void StoreAndHandlePointsAsync()
{
@ -154,7 +162,8 @@ public partial class RoundRunningViewModel : ObservableObject
{
RoundElements.FirstOrDefault(e => e.ParticipantId == col.PlayerId).GameRegPoints = col.PlayerPoints;
}
TriggerRebuild();
// TriggerRebuild();
BuildScore(playerColumns);
Shell.Current.GoToAsync("..").GetAwaiter().GetResult();
}
@ -290,6 +299,38 @@ public partial class RoundRunningViewModel : ObservableObject
}
}
public void BuildScore(IEnumerable<PlayerColumn> columns)
{
ScoreColumns.Clear();
foreach (var column in columns)
{
var scoreColumn = new ScoreColumn
{
PlayerName = column.PlayerName
};
scoreColumn.Cells.Add(new ScoreCell
{
Text = column.PlayerName,
IsHeader = true
});
foreach (var value in System.Linq.Enumerable.Reverse(column.Values))
{
scoreColumn.Cells.Add(new ScoreCell
{
Text = value,
IsHeader = false
});
}
ScoreColumns.Add(scoreColumn);
}
}
}

View File

@ -210,6 +210,7 @@ public partial class RoundStartingViewModel : ObservableObject
if (rbGroup != null)
{
_objectMessage.CurrentGroup = rbGroup;
//await Shell.Current.GoToAsync("//RoundRunningView");
await Shell.Current.GoToAsync("//RoundRunningView");
}
}

View File

@ -59,6 +59,14 @@
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Views\RoundRunningViewOld.xaml.cs" />
</ItemGroup>
<ItemGroup>
<MauiXaml Remove="Views\RoundRunningViewOld.xaml" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Maui" Version="12.2.0" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />

View File

@ -42,20 +42,24 @@ public static class MauiProgram
});
builder.Services.AddScoped<IRepository<Participant>, ParticipantRepository>();
builder.Services.AddScoped<IMethodSharingService<Participant>, MethodSharingService>();
builder.Services.AddScoped<ParticipantViewModel>();
builder.Services.AddScoped<ParticipantListView>();
builder.Services.AddScoped<IRepository<GameRound>, GameRoundRepository>();
builder.Services.AddScoped<RoundStartingViewModel>();
builder.Services.AddScoped<RoundStartingView>();
builder.Services.AddScoped<IRepository<GamePoint>, GamePointRepository>();
builder.Services.AddScoped<RoundRunningViewModel>();
builder.Services.AddScoped<RoundRunningView>();
builder.Services.AddScoped<IMethodSharingService<Participant>, MethodSharingService>();
builder.Services.AddScoped<ICombinedRepository, CombinedRepository>();
builder.Services.AddSingleton<IObjectMessageService, ObjectMessageService>();
builder.Services.AddTransientPopup<InfoPopup, InfoPopupViewModel>();
builder.Services.AddSingleton<IPopupEventHub, PopupEventHub>();

View File

@ -2,7 +2,10 @@
<?xaml-comp compile="true" ?>
<ResourceDictionary
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:GreadyPoang.Common;assembly=GreadyPoang.Common" >
<local:HeaderColorConverter x:Key="HeaderColorConverter" />
<Style TargetType="StackLayout" x:Key="ResponsiveStackStyle">
<Setter Property="Orientation" Value="Horizontal"/>

View File

@ -5,12 +5,16 @@
x:Class="GreadyPoang.Views.RoundRunningView"
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:RoundRunningViewModel"
Title="RoundRunningView">
<Border Style="{StaticResource Border.Page}" StrokeThickness="4">
<!--xmlns:local="clr-namespace:GreadyPoang.EntityLayer;assembly=GreadyPoang.EntityLayer"-->
<!--<ContentPage.Behaviors>
<behaviors:LoadedBehavior Command="{Binding OnLoadedCommand}" />
</ContentPage.Behaviors>-->
<Border
behaviors:LoadedBehavior.Command="{Binding OnLoadedCommand}"
Style="{StaticResource Border.Page}" StrokeThickness="4">
<Grid Style="{StaticResource Grid.Page}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
@ -87,14 +91,35 @@
Command="{Binding StoreAndHandlePointsAsyncCommand}"/>
</HorizontalStackLayout>
</Border>
<ScrollView Grid.Row="4" Orientation="Horizontal">
<Grid
x:Name="ScoreGrid"
ColumnSpacing="5"
RowSpacing="5"
Padding="3"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand" />
<HorizontalStackLayout
BindableLayout.ItemsSource="{Binding ScoreColumns}"
x:Name="ScoreGrid">
<BindableLayout.ItemTemplate>
<DataTemplate x:DataType="model:ScoreColumn">
<VerticalStackLayout BindableLayout.ItemsSource="{Binding Cells}">
<BindableLayout.ItemTemplate>
<DataTemplate x:DataType="model:ScoreCell">
<Border
Stroke="Gray"
StrokeThickness="1"
BackgroundColor="{Binding IsHeader, Converter={StaticResource HeaderColorConverter}}"
Margin="1"
Padding="2">
<Label
Text="{Binding Text}"
FontAttributes="{Binding IsHeader, Converter={StaticResource FontWeightConverter}}"
TextColor="{Binding IsHeader, Converter={StaticResource TextColorConverter}}"
HorizontalOptions="Center"
VerticalOptions="Center" />
</Border>
</DataTemplate>
</BindableLayout.ItemTemplate>
</VerticalStackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</HorizontalStackLayout>
</ScrollView>
</Grid>
</Border>

View File

@ -1,5 +1,4 @@
using GreadyPoang.EntityLayer;
using GreadyPoang.ViewModelLayer;
using GreadyPoang.ViewModelLayer;
namespace GreadyPoang.Views;
@ -8,98 +7,6 @@ public partial class RoundRunningView : ContentPage
public RoundRunningView(RoundRunningViewModel viewModel)
{
InitializeComponent();
ViewModel = viewModel;
ViewModel.RebuildRequested += ViewModel_RebuildRequested;
this.Loaded += OnPageLoaded;
}
private void OnPageLoaded(object? sender, EventArgs e)
{
ViewModel.Get();
}
protected override void OnAppearing()
{
base.OnAppearing();
BindingContext = ViewModel;
}
private void ViewModel_RebuildRequested(object? sender, EventArgs e)
{
BuildScoreGrid(ViewModel.PlayerColumns); // <-- h<>r bygger du layouten
}
//protected override
public RoundRunningViewModel ViewModel { get; set; }
private void BuildScoreGrid(IEnumerable<PlayerColumn> columns)
{
ScoreGrid.ColumnDefinitions.Clear();
ScoreGrid.RowDefinitions.Clear();
ScoreGrid.Children.Clear();
int maxRows = columns.Max(c => c.Values.Count);
// Skapa rader
for (int row = 0; row < maxRows + 1; row++) // +1 f<>r rubrikraden
{
ScoreGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
}
int colIndex = 0;
foreach (var column in columns)
{
ScoreGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
var headerCell = CreateCell(column.PlayerName, isHeader: true);
ScoreGrid.Children.Add(headerCell);
Grid.SetRow(headerCell, 0);
Grid.SetColumn(headerCell, colIndex);
// V<>rdeceller
for (int rowIndex = 0; rowIndex < column.Values.Count; rowIndex++)
{
var value = column.Values[rowIndex];
var cell = CreateCell(value);
ScoreGrid.Children.Add(cell);
Grid.SetRow(cell, column.Values.Count - rowIndex); // +1 f<>r att hoppa <20>ver rubrikraden
Grid.SetColumn(cell, colIndex);
}
colIndex++;
BindingContext = viewModel;
}
}
private View CreateCell(string text, bool isHeader = false)
{
return new Border
{
Stroke = Colors.Gray,
StrokeThickness = 1,
BackgroundColor = isHeader ? Colors.DarkGray : Colors.Yellow,
Margin = 1,
Padding = 2,
Content = new Label
{
Text = text,
FontAttributes = isHeader ? FontAttributes.Bold : FontAttributes.None,
TextColor = isHeader ? Colors.White : Colors.Black,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
}
};
}
protected override void OnDisappearing()
{
base.OnDisappearing();
ViewModel.PopupVisad = false;
}
}

View File

@ -0,0 +1,101 @@
<?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"
xmlns:partial="clr-namespace:GreadyPoang.ViewsPartial"
x:Class="GreadyPoang.Views.RoundRunningView"
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:RoundRunningViewModel"
Title="RoundRunningView">
<Border Style="{StaticResource Border.Page}" StrokeThickness="4">
<Grid Style="{StaticResource Grid.Page}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<partial:HeaderView Grid.Row="0"
Grid.ColumnSpan="2"
ViewTitle="Starta eller fortsätt en registrerad Runda"
ViewDescription="Deltagarna visas först!" />
<CollectionView Grid.Row="1"
ItemsSource="{Binding RoundElements}"
ItemsLayout="HorizontalList"
Margin="2">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="model:RoundBuilderElement">
<Border Stroke="Gray"
Padding="10"
Margin="5"
StrokeShape="RoundRectangle 10"
Style="{StaticResource StatusBorderStyle}">
<Border.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding Source={RelativeSource AncestorType={x:Type ContentPage}}, Path=BindingContext.ParticipantTappedCommand}"
CommandParameter="{Binding .}" />
</Border.GestureRecognizers>
<Grid VerticalOptions="Fill" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Text="Spelare" />
<Label Grid.Row="1" Text="{Binding ParticipantName}" FontAttributes="Bold" Style="{StaticResource StatusLabelStyle}" />
<Label Grid.Row="2" Text="{Binding GameRegPoints, StringFormat='Poäng: {0}'}" Style="{StaticResource StatusLabelStyle}" />
<Label Grid.Row="3" Text="{Binding Status}" Style="{StaticResource StatusLabelStyle}"/>
<Label Grid.Row="4" Text="{Binding GameRoundStartDate, StringFormat='Start: {0:yyyy-MM-dd}'}" Style="{StaticResource StatusLabelStyle}"/>
</Grid>
</Border>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<BoxView
Grid.Row="2"
Grid.ColumnSpan="2"
Margin="0,0,0,5"
HeightRequest="1"
Color="Black" />
<Border Grid.Row="3">
<HorizontalStackLayout>
<Grid VerticalOptions="Fill">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label Grid.Row="0" Text="{Binding BuilderObject.GameRoundId, StringFormat='Runda: {0}'}"/>
<Label Grid.Row="1" Text="{Binding BuilderObject.ParticipantName}" FontAttributes="Bold" FontSize="Subtitle" />
<Entry Grid.Row="2" x:Name="Points" Placeholder="Latest Points" Text="{Binding BuilderObject.GameRegPoints}" FontAttributes="Bold" FontSize="20" >
<Entry.Behaviors>
<behaviors:DigitsOnlyBehavior/>
<behaviors:EventToCommandBehavior EventName="Completed"
Command="{Binding StoreAndHandlePointsAsyncCommand}" />
</Entry.Behaviors>
</Entry>
</Grid>
<Button Text="Register Points"
Style="{StaticResource HoverButtonRedStyle}"
Command="{Binding StoreAndHandlePointsAsyncCommand}"/>
</HorizontalStackLayout>
</Border>
<ScrollView Grid.Row="4" Orientation="Horizontal">
<Grid
x:Name="ScoreGrid"
ColumnSpacing="5"
RowSpacing="5"
Padding="3"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand" />
</ScrollView>
</Grid>
</Border>
</ContentPage>

View File

@ -0,0 +1,105 @@
using GreadyPoang.EntityLayer;
using GreadyPoang.ViewModelLayer;
namespace GreadyPoang.Views;
public partial class RoundRunningView : ContentPage
{
public RoundRunningView(RoundRunningViewModel viewModel)
{
InitializeComponent();
ViewModel = viewModel;
ViewModel.RebuildRequested += ViewModel_RebuildRequested;
this.Loaded += OnPageLoaded;
}
private void OnPageLoaded(object? sender, EventArgs e)
{
ViewModel.Get();
}
protected override void OnAppearing()
{
base.OnAppearing();
BindingContext = ViewModel;
}
private void ViewModel_RebuildRequested(object? sender, EventArgs e)
{
BuildScoreGrid(ViewModel.PlayerColumns); // <-- h<>r bygger du layouten
}
//protected override
public RoundRunningViewModel ViewModel { get; set; }
private void BuildScoreGrid(IEnumerable<PlayerColumn> columns)
{
ScoreGrid.ColumnDefinitions.Clear();
ScoreGrid.RowDefinitions.Clear();
ScoreGrid.Children.Clear();
int maxRows = columns.Max(c => c.Values.Count);
// Skapa rader
for (int row = 0; row < maxRows + 1; row++) // +1 f<>r rubrikraden
{
ScoreGrid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
}
int colIndex = 0;
foreach (var column in columns)
{
ScoreGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
var headerCell = CreateCell(column.PlayerName, isHeader: true);
ScoreGrid.Children.Add(headerCell);
Grid.SetRow(headerCell, 0);
Grid.SetColumn(headerCell, colIndex);
// V<>rdeceller
for (int rowIndex = 0; rowIndex < column.Values.Count; rowIndex++)
{
var value = column.Values[rowIndex];
var cell = CreateCell(value);
ScoreGrid.Children.Add(cell);
Grid.SetRow(cell, column.Values.Count - rowIndex); // +1 f<>r att hoppa <20>ver rubrikraden
Grid.SetColumn(cell, colIndex);
}
colIndex++;
}
}
private View CreateCell(string text, bool isHeader = false)
{
return new Border
{
Stroke = Colors.Gray,
StrokeThickness = 1,
BackgroundColor = isHeader ? Colors.DarkGray : Colors.Yellow,
Margin = 1,
Padding = 2,
Content = new Label
{
Text = text,
FontAttributes = isHeader ? FontAttributes.Bold : FontAttributes.None,
TextColor = isHeader ? Colors.White : Colors.Black,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center
}
};
}
protected override void OnDisappearing()
{
base.OnDisappearing();
ViewModel.PopupVisad = false;
}
}