Use DataGridMyRatingColumn for both user and product ratings.

This commit is contained in:
Mbucari 2023-01-11 14:35:52 -07:00
parent b823f5fa00
commit fb18940a5c
9 changed files with 86 additions and 74 deletions

View file

@ -2,14 +2,24 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
using DataLayer;
using LibationAvalonia.ViewModels;
using ReactiveUI;
using System;
namespace LibationAvalonia.Controls
{
public class StarStringConverter : Avalonia.Data.Converters.IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
=> value is Rating rating ? rating.ToStarString() : string.Empty;
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
=> throw new NotImplementedException();
}
public class DataGridMyRatingColumn : DataGridBoundColumn
{
[Avalonia.Data.AssignBinding]
public Avalonia.Data.IBinding BackgroundBinding { get; set; }
private static Rating DefaultRating => new Rating(0, 0, 0);
public DataGridMyRatingColumn()
{
@ -24,29 +34,20 @@ namespace LibationAvalonia.Controls
IsEditingMode = false
};
ToolTip.SetTip(myRatingElement, "Click to change ratings");
cell?.AttachContextMenu();
if (!IsReadOnly)
ToolTip.SetTip(myRatingElement, "Click to change ratings");
if (Binding != null)
{
myRatingElement.Bind(BindingTarget, Binding);
}
void setControlBackground(object dataContext)
if (BackgroundBinding != null)
{
if (dataContext is GridEntry ge)
myRatingElement.Background = ge.BackgroundBrush;
myRatingElement.Bind(MyRatingCellEditor.BackgroundProperty, BackgroundBinding);
}
setControlBackground(cell?.DataContext);
var subscriber =
cell
?.ObservableForProperty(g => g.DataContext)
?.Subscribe(ctx => setControlBackground(ctx?.Value));
myRatingElement.DetachedFromVisualTree += (_, _) => subscriber?.Dispose();
return myRatingElement;
}
@ -57,6 +58,10 @@ namespace LibationAvalonia.Controls
Name = "CellMyRatingEditor",
IsEditingMode = true
};
if (BackgroundBinding != null)
{
myRatingElement.Bind(MyRatingCellEditor.BackgroundProperty, BackgroundBinding);
}
return myRatingElement;
}

View file

@ -17,7 +17,7 @@
</Grid.Styles>
<TextBlock Grid.Column="0" Grid.Row="0" Name="tblockOverall" Text="Overall:" />
<TextBlock Grid.Column="0" Grid.Row="1" Name="tblockPerform" Text="Perform:" />
<TextBlock Grid.Column="0" Grid.Row="1" Name="tblockPerform" Text="Perform: " />
<TextBlock Grid.Column="0" Grid.Row="2" Name="tblockStory" Text="Story:" />
<Panel Background="Transparent" PointerExited="Panel_PointerExited" Grid.Column="1" Grid.Row="0">

View file

@ -1,6 +1,8 @@
using Avalonia;
using Avalonia.Controls;
using DataLayer;
using ReactiveUI;
using System;
using System.Linq;
namespace LibationAvalonia.Controls
@ -9,6 +11,7 @@ namespace LibationAvalonia.Controls
{
private const string SOLID_STAR = "★";
private const string HOLLOW_STAR = "☆";
private const string HALF_STAR = "½";
public static readonly StyledProperty<Rating> RatingProperty =
AvaloniaProperty.Register<MyRatingCellEditor, Rating>(nameof(Rating));
@ -19,39 +22,41 @@ namespace LibationAvalonia.Controls
public MyRatingCellEditor()
{
InitializeComponent();
var subscriber = this.ObservableForProperty(p => p.Rating).Subscribe(o => DisplayStarRating(o.Value ?? new Rating(0, 0, 0)));
Unloaded += (_, _) => subscriber.Dispose();
if (Design.IsDesignMode)
Rating = new Rating(5, 4, 3);
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
private void DisplayStarRating(Rating rating)
{
if (change.Property.Name == nameof(Rating) && Rating is not null)
{
var blankValue = IsEditingMode ? HOLLOW_STAR : string.Empty;
var blankValue = IsEditingMode ? HOLLOW_STAR : string.Empty;
int rating = 0;
foreach (TextBlock star in panelOverall.Children)
star.Tag = star.Text = Rating.OverallRating > rating++ ? SOLID_STAR : blankValue;
string getStar(float score, int starIndex)
=> Math.Floor(score) > starIndex ? SOLID_STAR
: score < starIndex ? blankValue
: score - starIndex < 0.25 ? blankValue
: score - starIndex > 0.75 ? SOLID_STAR
: HALF_STAR;
rating = 0;
foreach (TextBlock star in panelPerform.Children)
star.Tag = star.Text = Rating.PerformanceRating > rating++ ? SOLID_STAR : blankValue;
int starIndex = 0;
foreach (TextBlock star in panelOverall.Children)
star.Tag = star.Text = getStar(rating.OverallRating, starIndex++);
rating = 0;
foreach (TextBlock star in panelStory.Children)
star.Tag = star.Text = Rating.StoryRating > rating++ ? SOLID_STAR : blankValue;
starIndex = 0;
foreach (TextBlock star in panelPerform.Children)
star.Tag = star.Text = getStar(rating.PerformanceRating, starIndex++);
SetVisible();
}
base.OnPropertyChanged(change);
}
starIndex = 0;
foreach (TextBlock star in panelStory.Children)
star.Tag = star.Text = getStar(rating.StoryRating, starIndex++);
private void SetVisible()
{
ratingsGrid.IsEnabled = IsEditingMode;
tblockOverall.IsVisible = panelOverall.IsVisible = IsEditingMode || Rating?.OverallRating > 0;
tblockPerform.IsVisible = panelPerform.IsVisible = IsEditingMode || Rating?.PerformanceRating > 0;
tblockStory.IsVisible = panelStory.IsVisible = IsEditingMode || Rating?.StoryRating > 0;
tblockOverall.IsVisible = panelOverall.IsVisible = IsEditingMode || rating.OverallRating > 0;
tblockPerform.IsVisible = panelPerform.IsVisible = IsEditingMode || rating.PerformanceRating > 0;
tblockStory.IsVisible = panelStory.IsVisible = IsEditingMode || rating.StoryRating > 0;
}
public void Panel_PointerExited(object sender, Avalonia.Input.PointerEventArgs e)