format BindableProperty & fix a tiny issue about rank page refreshing
This commit is contained in:
		@@ -16,6 +16,14 @@ namespace Billing.Languages
 | 
				
			|||||||
        public static string ConfirmDeleteBill => Text(nameof(ConfirmDeleteBill));
 | 
					        public static string ConfirmDeleteBill => Text(nameof(ConfirmDeleteBill));
 | 
				
			||||||
        public static string TitleDateFormat => Text(nameof(TitleDateFormat));
 | 
					        public static string TitleDateFormat => Text(nameof(TitleDateFormat));
 | 
				
			||||||
        public static string DateRangeFormat => Text(nameof(DateRangeFormat));
 | 
					        public static string DateRangeFormat => Text(nameof(DateRangeFormat));
 | 
				
			||||||
 | 
					        public static string Custom => Text(nameof(Custom));
 | 
				
			||||||
 | 
					        public static string Monthly => Text(nameof(Monthly));
 | 
				
			||||||
 | 
					        public static string Today => Text(nameof(Today));
 | 
				
			||||||
 | 
					        public static string PastMonth => Text(nameof(PastMonth));
 | 
				
			||||||
 | 
					        public static string PastQuarter => Text(nameof(PastQuarter));
 | 
				
			||||||
 | 
					        public static string PastSixMonths => Text(nameof(PastSixMonths));
 | 
				
			||||||
 | 
					        public static string PastYear => Text(nameof(PastYear));
 | 
				
			||||||
 | 
					        public static string Total => Text(nameof(Total));
 | 
				
			||||||
        public static string Cash => Text(nameof(Cash));
 | 
					        public static string Cash => Text(nameof(Cash));
 | 
				
			||||||
        public static string CreditCard => Text(nameof(CreditCard));
 | 
					        public static string CreditCard => Text(nameof(CreditCard));
 | 
				
			||||||
        public static string DebitCard => Text(nameof(DebitCard));
 | 
					        public static string DebitCard => Text(nameof(DebitCard));
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,6 +21,9 @@
 | 
				
			|||||||
	<TitleDateFormat>MM/dd/yyyy</TitleDateFormat>
 | 
						<TitleDateFormat>MM/dd/yyyy</TitleDateFormat>
 | 
				
			||||||
	<DateRangeFormat>MM/dd</DateRangeFormat>
 | 
						<DateRangeFormat>MM/dd</DateRangeFormat>
 | 
				
			||||||
	<To>To</To>
 | 
						<To>To</To>
 | 
				
			||||||
 | 
						<Type>Type</Type>
 | 
				
			||||||
 | 
						<Preset>Preset</Preset>
 | 
				
			||||||
 | 
						<Custom>Custom</Custom>
 | 
				
			||||||
	<Monthly>Monthly</Monthly>
 | 
						<Monthly>Monthly</Monthly>
 | 
				
			||||||
	<Today>Today</Today>
 | 
						<Today>Today</Today>
 | 
				
			||||||
	<PastMonth>Past Month</PastMonth>
 | 
						<PastMonth>Past Month</PastMonth>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,6 +21,9 @@
 | 
				
			|||||||
	<TitleDateFormat>yyyy年MM月dd日</TitleDateFormat>
 | 
						<TitleDateFormat>yyyy年MM月dd日</TitleDateFormat>
 | 
				
			||||||
	<DateRangeFormat>MM月dd日</DateRangeFormat>
 | 
						<DateRangeFormat>MM月dd日</DateRangeFormat>
 | 
				
			||||||
	<To>至</To>
 | 
						<To>至</To>
 | 
				
			||||||
 | 
						<Type>类型</Type>
 | 
				
			||||||
 | 
						<Preset>预设</Preset>
 | 
				
			||||||
 | 
						<Custom>自定义</Custom>
 | 
				
			||||||
	<Monthly>当月</Monthly>
 | 
						<Monthly>当月</Monthly>
 | 
				
			||||||
	<Today>今日</Today>
 | 
						<Today>今日</Today>
 | 
				
			||||||
	<PastMonth>一个月</PastMonth>
 | 
						<PastMonth>一个月</PastMonth>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -80,6 +80,14 @@ namespace Billing.Themes
 | 
				
			|||||||
                    new Setter { Property = TimePicker.FontFamilyProperty, Value = regularFontFamily }
 | 
					                    new Setter { Property = TimePicker.FontFamilyProperty, Value = regularFontFamily }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					            Add(new Style(typeof(OptionPicker))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Setters =
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    new Setter { Property = Picker.FontSizeProperty, Value = Device.GetNamedSize(NamedSize.Small, typeof(TimePicker)) },
 | 
				
			||||||
 | 
					                    new Setter { Property = Picker.FontFamilyProperty, Value = regularFontFamily }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
            Add(new Style(typeof(TintImage))
 | 
					            Add(new Style(typeof(TintImage))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                Setters =
 | 
					                Setters =
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,8 +34,8 @@ namespace Billing.UI
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public class LongPressGrid : Grid
 | 
					    public class LongPressGrid : Grid
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public static readonly BindableProperty LongCommandProperty = BindableProperty.Create(nameof(LongCommand), typeof(Command), typeof(LongPressGrid));
 | 
					        public static readonly BindableProperty LongCommandProperty = Helper.Create<Command, LongPressGrid>(nameof(LongCommand));
 | 
				
			||||||
        public static readonly BindableProperty LongCommandParameterProperty = BindableProperty.Create(nameof(LongCommandParameter), typeof(object), typeof(LongPressGrid));
 | 
					        public static readonly BindableProperty LongCommandParameterProperty = Helper.Create<object, LongPressGrid>(nameof(LongCommandParameter));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public Command LongCommand
 | 
					        public Command LongCommand
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,12 +5,12 @@ namespace Billing.UI
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    public class GroupStackLayout : Layout<View>
 | 
					    public class GroupStackLayout : Layout<View>
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public static readonly BindableProperty GroupHeaderTemplateProperty = BindableProperty.Create(nameof(GroupHeaderTemplate), typeof(DataTemplate), typeof(GroupStackLayout));
 | 
					        public static readonly BindableProperty GroupHeaderTemplateProperty = Helper.Create<DataTemplate, GroupStackLayout>(nameof(GroupHeaderTemplate));
 | 
				
			||||||
        public static readonly BindableProperty ItemTemplateProperty = BindableProperty.Create(nameof(ItemTemplate), typeof(DataTemplate), typeof(GroupStackLayout));
 | 
					        public static readonly BindableProperty ItemTemplateProperty = Helper.Create<DataTemplate, GroupStackLayout>(nameof(ItemTemplate));
 | 
				
			||||||
        public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(nameof(ItemsSource), typeof(IList), typeof(GroupStackLayout), propertyChanged: OnItemsSourcePropertyChanged);
 | 
					        public static readonly BindableProperty ItemsSourceProperty = Helper.Create<IList, GroupStackLayout>(nameof(ItemsSource), propertyChanged: OnItemsSourcePropertyChanged);
 | 
				
			||||||
        public static readonly BindableProperty SpacingProperty = BindableProperty.Create(nameof(Spacing), typeof(double), typeof(GroupStackLayout), defaultValue: 4d);
 | 
					        public static readonly BindableProperty SpacingProperty = Helper.Create<double, GroupStackLayout>(nameof(Spacing), defaultValue: 4d);
 | 
				
			||||||
        public static readonly BindableProperty RowHeightProperty = BindableProperty.Create(nameof(RowHeight), typeof(double), typeof(GroupStackLayout), defaultValue: 32d);
 | 
					        public static readonly BindableProperty RowHeightProperty = Helper.Create<double, GroupStackLayout>(nameof(RowHeight), defaultValue: 32d);
 | 
				
			||||||
        public static readonly BindableProperty GroupHeightProperty = BindableProperty.Create(nameof(GroupHeight), typeof(double), typeof(GroupStackLayout), defaultValue: 24d);
 | 
					        public static readonly BindableProperty GroupHeightProperty = Helper.Create<double, GroupStackLayout>(nameof(GroupHeight), defaultValue: 24d);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public DataTemplate GroupHeaderTemplate
 | 
					        public DataTemplate GroupHeaderTemplate
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -43,17 +43,16 @@ namespace Billing.UI
 | 
				
			|||||||
            set => SetValue(GroupHeightProperty, value);
 | 
					            set => SetValue(GroupHeightProperty, value);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private static void OnItemsSourcePropertyChanged(BindableObject obj, object old, object @new)
 | 
					        private static void OnItemsSourcePropertyChanged(GroupStackLayout stack, IList old, IList list)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var stack = (GroupStackLayout)obj;
 | 
					 | 
				
			||||||
            stack.lastWidth = -1;
 | 
					            stack.lastWidth = -1;
 | 
				
			||||||
            if (@new == null)
 | 
					            if (list == null)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                //stack.cachedLayout.Clear();
 | 
					                //stack.cachedLayout.Clear();
 | 
				
			||||||
                stack.Children.Clear();
 | 
					                stack.Children.Clear();
 | 
				
			||||||
                stack.InvalidateLayout();
 | 
					                stack.InvalidateLayout();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else if (@new is IList list)
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                stack.freezed = true;
 | 
					                stack.freezed = true;
 | 
				
			||||||
                //stack.cachedLayout.Clear();
 | 
					                //stack.cachedLayout.Clear();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,16 +4,32 @@ using Xamarin.Forms;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Billing.UI
 | 
					namespace Billing.UI
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    public enum BorderStyle
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        None = 0,
 | 
				
			||||||
 | 
					        RoundedRect
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public class OptionEntry : Entry { }
 | 
					    public class OptionEntry : Entry { }
 | 
				
			||||||
    public class OptionEditor : Editor { }
 | 
					    public class OptionEditor : Editor { }
 | 
				
			||||||
 | 
					    public class OptionPicker : Picker
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public static readonly BindableProperty BorderStyleProperty = Helper.Create<BorderStyle, OptionPicker>(nameof(BorderStyle));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public BorderStyle BorderStyle
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get => (BorderStyle)GetValue(BorderStyleProperty);
 | 
				
			||||||
 | 
					            set => SetValue(BorderStyleProperty, value);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    public class OptionDatePicker : DatePicker { }
 | 
					    public class OptionDatePicker : DatePicker { }
 | 
				
			||||||
    public class OptionTimePicker : TimePicker { }
 | 
					    public class OptionTimePicker : TimePicker { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public abstract class OptionCell : ViewCell
 | 
					    public abstract class OptionCell : ViewCell
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public static readonly BindableProperty TitleProperty = BindableProperty.Create(nameof(Title), typeof(string), typeof(OptionCell));
 | 
					        public static readonly BindableProperty TitleProperty = Helper.Create<string, OptionCell>(nameof(Title));
 | 
				
			||||||
        public static readonly BindableProperty BackgroundColorProperty = BindableProperty.Create(nameof(BackgroundColor), typeof(Color), typeof(OptionCell));
 | 
					        public static readonly BindableProperty BackgroundColorProperty = Helper.Create<Color, OptionCell>(nameof(BackgroundColor));
 | 
				
			||||||
        public static readonly BindableProperty IconProperty = BindableProperty.Create(nameof(Icon), typeof(ImageSource), typeof(OptionCell));
 | 
					        public static readonly BindableProperty IconProperty = Helper.Create<ImageSource, OptionCell>(nameof(Icon));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public string Title
 | 
					        public string Title
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -124,7 +140,7 @@ namespace Billing.UI
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public class OptionTextCell : OptionCell
 | 
					    public class OptionTextCell : OptionCell
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public static readonly BindableProperty DetailProperty = BindableProperty.Create(nameof(Detail), typeof(string), typeof(OptionTextCell));
 | 
					        public static readonly BindableProperty DetailProperty = Helper.Create<string, OptionTextCell>(nameof(Detail));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public string Detail
 | 
					        public string Detail
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -143,8 +159,8 @@ namespace Billing.UI
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public class OptionSelectCell : OptionTextCell
 | 
					    public class OptionSelectCell : OptionTextCell
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public static readonly BindableProperty CommandProperty = BindableProperty.Create(nameof(Command), typeof(Command), typeof(OptionSelectCell));
 | 
					        public static readonly BindableProperty CommandProperty = Helper.Create<Command, OptionSelectCell>(nameof(Command));
 | 
				
			||||||
        public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create(nameof(CommandParameter), typeof(object), typeof(OptionSelectCell));
 | 
					        public static readonly BindableProperty CommandParameterProperty = Helper.Create<object, OptionSelectCell>(nameof(CommandParameter));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public Command Command
 | 
					        public Command Command
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -189,8 +205,8 @@ namespace Billing.UI
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public class OptionImageCell : OptionSelectCell
 | 
					    public class OptionImageCell : OptionSelectCell
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public static readonly BindableProperty ImageSourceProperty = BindableProperty.Create(nameof(ImageSource), typeof(ImageSource), typeof(OptionImageCell));
 | 
					        public static readonly BindableProperty ImageSourceProperty = Helper.Create<ImageSource, OptionImageCell>(nameof(ImageSource));
 | 
				
			||||||
        public static readonly BindableProperty TintColorProperty = BindableProperty.Create(nameof(TintColor), typeof(Color?), typeof(OptionImageCell));
 | 
					        public static readonly BindableProperty TintColorProperty = Helper.Create<Color?, OptionImageCell>(nameof(TintColor));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [TypeConverter(typeof(ImageSourceConverter))]
 | 
					        [TypeConverter(typeof(ImageSourceConverter))]
 | 
				
			||||||
        public ImageSource ImageSource
 | 
					        public ImageSource ImageSource
 | 
				
			||||||
@@ -240,7 +256,7 @@ namespace Billing.UI
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public class OptionSwitchCell : OptionCell
 | 
					    public class OptionSwitchCell : OptionCell
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public static readonly BindableProperty IsToggledProperty = BindableProperty.Create(nameof(IsToggled), typeof(bool), typeof(OptionSwitchCell));
 | 
					        public static readonly BindableProperty IsToggledProperty = Helper.Create<bool, OptionSwitchCell>(nameof(IsToggled));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public bool IsToggled
 | 
					        public bool IsToggled
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -258,7 +274,7 @@ namespace Billing.UI
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public class OptionDatePickerCell : OptionCell
 | 
					    public class OptionDatePickerCell : OptionCell
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public static readonly BindableProperty DateProperty = BindableProperty.Create(nameof(Date), typeof(DateTime), typeof(OptionDatePickerCell));
 | 
					        public static readonly BindableProperty DateProperty = Helper.Create<DateTime, OptionDatePickerCell>(nameof(Date));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public DateTime Date
 | 
					        public DateTime Date
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -278,7 +294,7 @@ namespace Billing.UI
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public class OptionTimePickerCell : OptionCell
 | 
					    public class OptionTimePickerCell : OptionCell
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public static readonly BindableProperty TimeProperty = BindableProperty.Create(nameof(Time), typeof(TimeSpan), typeof(OptionTimePickerCell));
 | 
					        public static readonly BindableProperty TimeProperty = Helper.Create<TimeSpan, OptionTimePickerCell>(nameof(Time));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public TimeSpan Time
 | 
					        public TimeSpan Time
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -298,9 +314,9 @@ namespace Billing.UI
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public class OptionEntryCell : OptionCell
 | 
					    public class OptionEntryCell : OptionCell
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public static readonly BindableProperty TextProperty = BindableProperty.Create(nameof(Text), typeof(string), typeof(OptionEntryCell));
 | 
					        public static readonly BindableProperty TextProperty = Helper.Create<string, OptionEntryCell>(nameof(Text));
 | 
				
			||||||
        public static readonly BindableProperty KeyboardProperty = BindableProperty.Create(nameof(Keyboard), typeof(Keyboard), typeof(OptionEntryCell));
 | 
					        public static readonly BindableProperty KeyboardProperty = Helper.Create<Keyboard, OptionEntryCell>(nameof(Keyboard), defaultValue: Keyboard.Default);
 | 
				
			||||||
        public static readonly BindableProperty PlaceholderProperty = BindableProperty.Create(nameof(Placeholder), typeof(string), typeof(OptionEntryCell));
 | 
					        public static readonly BindableProperty PlaceholderProperty = Helper.Create<string, OptionEntryCell>(nameof(Placeholder));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public string Text
 | 
					        public string Text
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -351,10 +367,10 @@ namespace Billing.UI
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public class OptionEditorCell : OptionVerticalCell
 | 
					    public class OptionEditorCell : OptionVerticalCell
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public static readonly BindableProperty TextProperty = BindableProperty.Create(nameof(Text), typeof(string), typeof(OptionEditorCell));
 | 
					        public static readonly BindableProperty TextProperty = Helper.Create<string, OptionEditorCell>(nameof(Text));
 | 
				
			||||||
        public static readonly BindableProperty FontSizeProperty = BindableProperty.Create(nameof(FontSize), typeof(double), typeof(OptionEditorCell), defaultValue: Device.GetNamedSize(NamedSize.Default, typeof(Editor)));
 | 
					        public static readonly BindableProperty FontSizeProperty = Helper.Create<double, OptionEditorCell>(nameof(FontSize), defaultValue: Device.GetNamedSize(NamedSize.Default, typeof(Editor)));
 | 
				
			||||||
        public static readonly BindableProperty KeyboardProperty = BindableProperty.Create(nameof(Keyboard), typeof(Keyboard), typeof(OptionEditorCell), defaultValue: Keyboard.Default);
 | 
					        public static readonly BindableProperty KeyboardProperty = Helper.Create<Keyboard, OptionEditorCell>(nameof(Keyboard), defaultValue: Keyboard.Default);
 | 
				
			||||||
        public static readonly BindableProperty PlaceholderProperty = BindableProperty.Create(nameof(Placeholder), typeof(string), typeof(OptionEditorCell));
 | 
					        public static readonly BindableProperty PlaceholderProperty = Helper.Create<string, OptionEditorCell>(nameof(Placeholder));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public string Text
 | 
					        public string Text
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,24 +7,23 @@ namespace Billing.UI
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    public class WrapLayout : Layout<View>
 | 
					    public class WrapLayout : Layout<View>
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(nameof(ItemsSource), typeof(IList), typeof(WrapLayout), propertyChanged: OnItemsSourcePropertyChanged);
 | 
					        public static readonly BindableProperty ItemsSourceProperty = Helper.Create<IList, WrapLayout>(nameof(ItemsSource), propertyChanged: OnItemsSourcePropertyChanged);
 | 
				
			||||||
        public static readonly BindableProperty ColumnSpacingProperty = BindableProperty.Create(nameof(ColumnSpacing), typeof(double), typeof(WrapLayout), defaultValue: 4d, propertyChanged: (obj, _, _) => ((WrapLayout)obj).InvalidateLayout());
 | 
					        public static readonly BindableProperty ColumnSpacingProperty = Helper.Create<double, WrapLayout>(nameof(ColumnSpacing), defaultValue: 4d, propertyChanged: (layout, _, _) => layout.InvalidateLayout());
 | 
				
			||||||
        public static readonly BindableProperty RowSpacingProperty = BindableProperty.Create(nameof(RowSpacing), typeof(double), typeof(WrapLayout), defaultValue: 4d, propertyChanged: (obj, _, _) => ((WrapLayout)obj).InvalidateLayout());
 | 
					        public static readonly BindableProperty RowSpacingProperty = Helper.Create<double, WrapLayout>(nameof(RowSpacing), defaultValue: 4d, propertyChanged: (layout, _, _) => layout.InvalidateLayout());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private static void OnItemsSourcePropertyChanged(BindableObject obj, object old, object @new)
 | 
					        private static void OnItemsSourcePropertyChanged(WrapLayout layout, IList old, IList list)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var itemTemplate = BindableLayout.GetItemTemplate(obj);
 | 
					            var itemTemplate = BindableLayout.GetItemTemplate(layout);
 | 
				
			||||||
            if (itemTemplate == null)
 | 
					            if (itemTemplate == null)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            var layout = (WrapLayout)obj;
 | 
					            if (list == null)
 | 
				
			||||||
            if (@new == null)
 | 
					 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                layout.Children.Clear();
 | 
					                layout.Children.Clear();
 | 
				
			||||||
                layout.InvalidateLayout();
 | 
					                layout.InvalidateLayout();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else if (@new is IList list)
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                layout.freezed = true;
 | 
					                layout.freezed = true;
 | 
				
			||||||
                layout.Children.Clear();
 | 
					                layout.Children.Clear();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,10 +10,10 @@ namespace Billing.Views
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    public partial class AccountPage : BillingPage
 | 
					    public partial class AccountPage : BillingPage
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private static readonly BindableProperty BalanceProperty = BindableProperty.Create(nameof(Balance), typeof(decimal), typeof(AccountPage));
 | 
					        private static readonly BindableProperty BalanceProperty = Helper.Create<decimal, AccountPage>(nameof(Balance));
 | 
				
			||||||
        private static readonly BindableProperty AssetProperty = BindableProperty.Create(nameof(Asset), typeof(decimal), typeof(AccountPage));
 | 
					        private static readonly BindableProperty AssetProperty = Helper.Create<decimal, AccountPage>(nameof(Asset));
 | 
				
			||||||
        private static readonly BindableProperty LiabilityProperty = BindableProperty.Create(nameof(Liability), typeof(decimal), typeof(AccountPage));
 | 
					        private static readonly BindableProperty LiabilityProperty = Helper.Create<decimal, AccountPage>(nameof(Liability));
 | 
				
			||||||
        private static readonly BindableProperty AccountsProperty = BindableProperty.Create(nameof(Accounts), typeof(List<AccountGrouping>), typeof(AccountPage));
 | 
					        private static readonly BindableProperty AccountsProperty = Helper.Create<List<AccountGrouping>, AccountPage>(nameof(Accounts));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public decimal Balance => (decimal)GetValue(BalanceProperty);
 | 
					        public decimal Balance => (decimal)GetValue(BalanceProperty);
 | 
				
			||||||
        public decimal Asset => (decimal)GetValue(AssetProperty);
 | 
					        public decimal Asset => (decimal)GetValue(AssetProperty);
 | 
				
			||||||
@@ -130,6 +130,8 @@ namespace Billing.Views
 | 
				
			|||||||
                        RefreshBalance();
 | 
					                        RefreshBalance();
 | 
				
			||||||
                        groupLayout.Refresh(accounts);
 | 
					                        groupLayout.Refresh(accounts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        RankPage.Instance?.SetNeedRefresh();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        _ = Task.Run(App.WriteAccounts);
 | 
					                        _ = Task.Run(App.WriteAccounts);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@@ -147,6 +149,8 @@ namespace Billing.Views
 | 
				
			|||||||
            RefreshBalance(!add);
 | 
					            RefreshBalance(!add);
 | 
				
			||||||
            groupLayout.Refresh(accounts);
 | 
					            groupLayout.Refresh(accounts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            RankPage.Instance?.SetNeedRefresh();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Task.Run(App.WriteAccounts);
 | 
					            Task.Run(App.WriteAccounts);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,11 +9,11 @@ namespace Billing.Views
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    public partial class AddAccountPage : BillingPage
 | 
					    public partial class AddAccountPage : BillingPage
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private static readonly BindableProperty AccountNameProperty = BindableProperty.Create(nameof(AccountName), typeof(string), typeof(AddAccountPage));
 | 
					        private static readonly BindableProperty AccountNameProperty = Helper.Create<string, AddAccountPage>(nameof(AccountName));
 | 
				
			||||||
        private static readonly BindableProperty AccountIconProperty = BindableProperty.Create(nameof(AccountIcon), typeof(string), typeof(AddAccountPage));
 | 
					        private static readonly BindableProperty AccountIconProperty = Helper.Create<string, AddAccountPage>(nameof(AccountIcon));
 | 
				
			||||||
        private static readonly BindableProperty CategoryProperty = BindableProperty.Create(nameof(Category), typeof(AccountCategory), typeof(AddAccountPage));
 | 
					        private static readonly BindableProperty CategoryProperty = Helper.Create<AccountCategory, AddAccountPage>(nameof(Category));
 | 
				
			||||||
        private static readonly BindableProperty InitialProperty = BindableProperty.Create(nameof(Initial), typeof(string), typeof(AddAccountPage));
 | 
					        private static readonly BindableProperty InitialProperty = Helper.Create<string, AddAccountPage>(nameof(Initial));
 | 
				
			||||||
        private static readonly BindableProperty MemoProperty = BindableProperty.Create(nameof(Memo), typeof(string), typeof(AddAccountPage));
 | 
					        private static readonly BindableProperty MemoProperty = Helper.Create<string, AddAccountPage>(nameof(Memo));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public string AccountName
 | 
					        public string AccountName
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,14 +10,14 @@ namespace Billing.Views
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    public partial class AddBillPage : BillingPage
 | 
					    public partial class AddBillPage : BillingPage
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private static readonly BindableProperty AmountProperty = BindableProperty.Create(nameof(Amount), typeof(string), typeof(AddBillPage));
 | 
					        private static readonly BindableProperty AmountProperty = Helper.Create<string, AddBillPage>(nameof(Amount));
 | 
				
			||||||
        private static readonly BindableProperty NameProperty = BindableProperty.Create(nameof(Name), typeof(string), typeof(AddBillPage));
 | 
					        private static readonly BindableProperty NameProperty = Helper.Create<string, AddBillPage>(nameof(Name));
 | 
				
			||||||
        private static readonly BindableProperty CategoryNameProperty = BindableProperty.Create(nameof(CategoryName), typeof(string), typeof(AddBillPage));
 | 
					        private static readonly BindableProperty CategoryNameProperty = Helper.Create<string, AddBillPage>(nameof(CategoryName));
 | 
				
			||||||
        private static readonly BindableProperty WalletNameProperty = BindableProperty.Create(nameof(WalletName), typeof(string), typeof(AddBillPage));
 | 
					        private static readonly BindableProperty WalletNameProperty = Helper.Create<string, AddBillPage>(nameof(WalletName));
 | 
				
			||||||
        private static readonly BindableProperty StoreProperty = BindableProperty.Create(nameof(Store), typeof(string), typeof(AddBillPage));
 | 
					        private static readonly BindableProperty StoreProperty = Helper.Create<string, AddBillPage>(nameof(Store));
 | 
				
			||||||
        private static readonly BindableProperty CreatedDateProperty = BindableProperty.Create(nameof(CreatedDate), typeof(DateTime), typeof(AddBillPage));
 | 
					        private static readonly BindableProperty CreatedDateProperty = Helper.Create<DateTime, AddBillPage>(nameof(CreatedDate));
 | 
				
			||||||
        private static readonly BindableProperty CreatedTimeProperty = BindableProperty.Create(nameof(CreatedTime), typeof(TimeSpan), typeof(AddBillPage));
 | 
					        private static readonly BindableProperty CreatedTimeProperty = Helper.Create<TimeSpan, AddBillPage>(nameof(CreatedTime));
 | 
				
			||||||
        private static readonly BindableProperty NoteProperty = BindableProperty.Create(nameof(Note), typeof(string), typeof(AddBillPage));
 | 
					        private static readonly BindableProperty NoteProperty = Helper.Create<string, AddBillPage>(nameof(Note));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public string Amount
 | 
					        public string Amount
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,10 +10,10 @@ namespace Billing.Views
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    public partial class AddCategoryPage : BillingPage
 | 
					    public partial class AddCategoryPage : BillingPage
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private static readonly BindableProperty CategoryNameProperty = BindableProperty.Create(nameof(CategoryName), typeof(string), typeof(AddCategoryPage));
 | 
					        private static readonly BindableProperty CategoryNameProperty = Helper.Create<string, AddCategoryPage>(nameof(CategoryName));
 | 
				
			||||||
        private static readonly BindableProperty CategoryIconProperty = BindableProperty.Create(nameof(CategoryIcon), typeof(string), typeof(AddCategoryPage));
 | 
					        private static readonly BindableProperty CategoryIconProperty = Helper.Create<string, AddCategoryPage>(nameof(CategoryIcon));
 | 
				
			||||||
        private static readonly BindableProperty TintColorProperty = BindableProperty.Create(nameof(TintColor), typeof(Color), typeof(AddCategoryPage));
 | 
					        private static readonly BindableProperty TintColorProperty = Helper.Create<Color, AddCategoryPage>(nameof(TintColor));
 | 
				
			||||||
        private static readonly BindableProperty TintColorStringProperty = BindableProperty.Create(nameof(TintColorString), typeof(string), typeof(AddCategoryPage));
 | 
					        private static readonly BindableProperty TintColorStringProperty = Helper.Create<string, AddCategoryPage>(nameof(TintColorString));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public string CategoryName
 | 
					        public string CategoryName
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -156,6 +156,8 @@ namespace Billing.Views
 | 
				
			|||||||
                        billsLayout.Refresh(bills);
 | 
					                        billsLayout.Refresh(bills);
 | 
				
			||||||
                        RefreshBalance(bills);
 | 
					                        RefreshBalance(bills);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        RankPage.Instance?.SetNeedRefresh();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        _ = Task.Run(App.WriteBills);
 | 
					                        _ = Task.Run(App.WriteBills);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@@ -191,17 +193,19 @@ namespace Billing.Views
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            RefreshBalance(Bills);
 | 
					            RefreshBalance(Bills);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            RankPage.Instance?.SetNeedRefresh();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Task.Run(App.WriteBills);
 | 
					            Task.Run(App.WriteBills);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public class UIBill : BindableObject
 | 
					    public class UIBill : BindableObject
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public static readonly BindableProperty IconProperty = BindableProperty.Create(nameof(Icon), typeof(string), typeof(UIBill));
 | 
					        public static readonly BindableProperty IconProperty = Helper.Create<string, UIBill>(nameof(Icon));
 | 
				
			||||||
        public static readonly BindableProperty NameProperty = BindableProperty.Create(nameof(Name), typeof(string), typeof(UIBill));
 | 
					        public static readonly BindableProperty NameProperty = Helper.Create<string, UIBill>(nameof(Name));
 | 
				
			||||||
        public static readonly BindableProperty DateCreationProperty = BindableProperty.Create(nameof(DateCreation), typeof(DateTime), typeof(UIBill));
 | 
					        public static readonly BindableProperty DateCreationProperty = Helper.Create<DateTime, UIBill>(nameof(DateCreation));
 | 
				
			||||||
        public static readonly BindableProperty AmountProperty = BindableProperty.Create(nameof(Amount), typeof(decimal), typeof(UIBill));
 | 
					        public static readonly BindableProperty AmountProperty = Helper.Create<decimal, UIBill>(nameof(Amount));
 | 
				
			||||||
        public static readonly BindableProperty WalletProperty = BindableProperty.Create(nameof(Wallet), typeof(string), typeof(UIBill));
 | 
					        public static readonly BindableProperty WalletProperty = Helper.Create<string, UIBill>(nameof(Wallet));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public string Icon
 | 
					        public string Icon
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,8 +12,8 @@ namespace Billing.Views
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    public partial class CategoryPage : BillingPage
 | 
					    public partial class CategoryPage : BillingPage
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private static readonly BindableProperty CategoriesProperty = BindableProperty.Create(nameof(Categories), typeof(IList), typeof(CategoryPage));
 | 
					        private static readonly BindableProperty CategoriesProperty = Helper.Create<IList, CategoryPage>(nameof(Categories));
 | 
				
			||||||
        private static readonly BindableProperty IsTopCategoryProperty = BindableProperty.Create(nameof(IsTopCategory), typeof(bool), typeof(CategoryPage));
 | 
					        private static readonly BindableProperty IsTopCategoryProperty = Helper.Create<bool, CategoryPage>(nameof(IsTopCategory));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public IList Categories
 | 
					        public IList Categories
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -198,11 +198,11 @@ namespace Billing.Views
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public class UICategory : BindableObject
 | 
					    public class UICategory : BindableObject
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public static readonly BindableProperty IsCheckedProperty = BindableProperty.Create(nameof(IsChecked), typeof(bool), typeof(UICategory));
 | 
					        public static readonly BindableProperty IsCheckedProperty = Helper.Create<bool, UICategory>(nameof(IsChecked));
 | 
				
			||||||
        public static readonly BindableProperty IconProperty = BindableProperty.Create(nameof(Icon), typeof(string), typeof(UICategory));
 | 
					        public static readonly BindableProperty IconProperty = Helper.Create<string, UICategory>(nameof(Icon));
 | 
				
			||||||
        public static readonly BindableProperty NameProperty = BindableProperty.Create(nameof(Name), typeof(string), typeof(UICategory));
 | 
					        public static readonly BindableProperty NameProperty = Helper.Create<string, UICategory>(nameof(Name));
 | 
				
			||||||
        public static readonly BindableProperty TintColorProperty = BindableProperty.Create(nameof(TintColor), typeof(Color), typeof(UICategory));
 | 
					        public static readonly BindableProperty TintColorProperty = Helper.Create<Color, UICategory>(nameof(TintColor));
 | 
				
			||||||
        public static readonly BindableProperty IsTopCategoryProperty = BindableProperty.Create(nameof(IsTopCategory), typeof(bool), typeof(UICategory));
 | 
					        public static readonly BindableProperty IsTopCategoryProperty = Helper.Create<bool, UICategory>(nameof(IsTopCategory));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public bool IsChecked
 | 
					        public bool IsChecked
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,8 +11,8 @@ namespace Billing.Views
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    public partial class CategorySelectPage : BillingPage
 | 
					    public partial class CategorySelectPage : BillingPage
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private static readonly BindableProperty TopCategoriesProperty = BindableProperty.Create(nameof(TopCategories), typeof(List<CategoryGrouping>), typeof(CategorySelectPage));
 | 
					        private static readonly BindableProperty TopCategoriesProperty = Helper.Create<List<CategoryGrouping>, CategorySelectPage>(nameof(TopCategories));
 | 
				
			||||||
        private static readonly BindableProperty SubCategoriesProperty = BindableProperty.Create(nameof(SubCategories), typeof(List<UICategory>), typeof(CategorySelectPage));
 | 
					        private static readonly BindableProperty SubCategoriesProperty = Helper.Create<List<UICategory>, CategorySelectPage>(nameof(SubCategories));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public List<CategoryGrouping> TopCategories
 | 
					        public List<CategoryGrouping> TopCategories
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,7 +9,7 @@ namespace Billing.Views
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    public partial class IconSelectPage : BillingPage
 | 
					    public partial class IconSelectPage : BillingPage
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public static readonly BindableProperty IconsSourceProperty = BindableProperty.Create(nameof(IconsSource), typeof(IList<BillingIcon>), typeof(IconSelectPage));
 | 
					        public static readonly BindableProperty IconsSourceProperty = Helper.Create<IList<BillingIcon>, IconSelectPage>(nameof(IconsSource));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public IList<BillingIcon> IconsSource
 | 
					        public IList<BillingIcon> IconsSource
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@@ -103,7 +103,7 @@ namespace Billing.Views
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public class BillingIcon : BindableObject
 | 
					    public class BillingIcon : BindableObject
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public static readonly BindableProperty IsCheckedProperty = BindableProperty.Create(nameof(IsChecked), typeof(bool), typeof(BillingIcon));
 | 
					        public static readonly BindableProperty IsCheckedProperty = Helper.Create<bool, BillingIcon>(nameof(IsChecked));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public bool IsChecked
 | 
					        public bool IsChecked
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -142,7 +142,7 @@
 | 
				
			|||||||
                        BackgroundColor="{DynamicResource WindowBackgroundColor}"
 | 
					                        BackgroundColor="{DynamicResource WindowBackgroundColor}"
 | 
				
			||||||
                        HeightRequest="{Binding Height, Source={x:Reference gridFilter}}"/>
 | 
					                        HeightRequest="{Binding Height, Source={x:Reference gridFilter}}"/>
 | 
				
			||||||
        <Grid x:Name="gridFilter" VerticalOptions="Start" Opacity="0" RowDefinitions="Auto, Auto, Auto, Auto">
 | 
					        <Grid x:Name="gridFilter" VerticalOptions="Start" Opacity="0" RowDefinitions="Auto, Auto, Auto, Auto">
 | 
				
			||||||
            <ui:SegmentedControl Margin="16, 16, 16, 3" VerticalOptions="Center"
 | 
					            <ui:SegmentedControl VerticalOptions="Center" Margin="10, 10, 10, 3"
 | 
				
			||||||
                                 SelectedSegmentIndex="{Binding SegmentType, Mode=TwoWay}"
 | 
					                                 SelectedSegmentIndex="{Binding SegmentType, Mode=TwoWay}"
 | 
				
			||||||
                                 SelectedTextColor="{DynamicResource TextColor}"
 | 
					                                 SelectedTextColor="{DynamicResource TextColor}"
 | 
				
			||||||
                                 TintColor="{DynamicResource PromptBackgroundColor}">
 | 
					                                 TintColor="{DynamicResource PromptBackgroundColor}">
 | 
				
			||||||
@@ -151,22 +151,13 @@
 | 
				
			|||||||
                    <ui:SegmentedControlOption Text="{r:Text Income}"/>
 | 
					                    <ui:SegmentedControlOption Text="{r:Text Income}"/>
 | 
				
			||||||
                </ui:SegmentedControl.Children>
 | 
					                </ui:SegmentedControl.Children>
 | 
				
			||||||
            </ui:SegmentedControl>
 | 
					            </ui:SegmentedControl>
 | 
				
			||||||
            <ScrollView Grid.Row="1" Margin="16, 6, 16, 3">
 | 
					            <ui:OptionPicker Grid.Row="1" VerticalOptions="Center" Margin="10, 3"
 | 
				
			||||||
                <ui:SegmentedControl SelectedSegmentIndex="{Binding SegmentDate, Mode=TwoWay}"
 | 
					                             HorizontalTextAlignment="Center" FontSize="16"
 | 
				
			||||||
                                     SelectedTextColor="{DynamicResource TextColor}"
 | 
					                             ItemsSource="{Binding DateTypes}"
 | 
				
			||||||
                                     TintColor="{DynamicResource PromptBackgroundColor}">
 | 
					                             SelectedIndex="{Binding SegmentDate, Mode=TwoWay}"
 | 
				
			||||||
                    <ui:SegmentedControl.Children>
 | 
					                             TextColor="{DynamicResource TextColor}"
 | 
				
			||||||
                        <ui:SegmentedControlOption Text="{r:Text Monthly}"/>
 | 
					                             ios:Picker.UpdateMode="WhenFinished"/>
 | 
				
			||||||
                        <ui:SegmentedControlOption Text="{r:Text Today}"/>
 | 
					            <Grid Grid.Row="2" ColumnDefinitions="*, Auto, *" Margin="10, 3">
 | 
				
			||||||
                        <ui:SegmentedControlOption Text="{r:Text PastMonth}"/>
 | 
					 | 
				
			||||||
                        <ui:SegmentedControlOption Text="{r:Text PastQuarter}"/>
 | 
					 | 
				
			||||||
                        <ui:SegmentedControlOption Text="{r:Text PastSixMonths}"/>
 | 
					 | 
				
			||||||
                        <ui:SegmentedControlOption Text="{r:Text PastYear}"/>
 | 
					 | 
				
			||||||
                        <ui:SegmentedControlOption Text="{r:Text Total}"/>
 | 
					 | 
				
			||||||
                    </ui:SegmentedControl.Children>
 | 
					 | 
				
			||||||
                </ui:SegmentedControl>
 | 
					 | 
				
			||||||
            </ScrollView>
 | 
					 | 
				
			||||||
            <Grid Grid.Row="2" ColumnDefinitions="*, Auto, *" Margin="10">
 | 
					 | 
				
			||||||
                <ui:OptionDatePicker Date="{Binding StartPickerDate, Mode=TwoWay}"
 | 
					                <ui:OptionDatePicker Date="{Binding StartPickerDate, Mode=TwoWay}"
 | 
				
			||||||
                                     FontSize="16" TextColor="{DynamicResource TextColor}"
 | 
					                                     FontSize="16" TextColor="{DynamicResource TextColor}"
 | 
				
			||||||
                                     VerticalOptions="Center"
 | 
					                                     VerticalOptions="Center"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,7 +16,8 @@ namespace Billing.Views
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    public enum DateType : int
 | 
					    public enum DateType : int
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        Monthly = 0,
 | 
					        Custom = 0,
 | 
				
			||||||
 | 
					        Monthly,
 | 
				
			||||||
        Today,
 | 
					        Today,
 | 
				
			||||||
        PastMonth,
 | 
					        PastMonth,
 | 
				
			||||||
        PastQuarter,
 | 
					        PastQuarter,
 | 
				
			||||||
@@ -27,10 +28,13 @@ namespace Billing.Views
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public partial class RankPage : BillingPage
 | 
					    public partial class RankPage : BillingPage
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        private static RankPage instance;
 | 
				
			||||||
 | 
					        public static RankPage Instance => instance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private static readonly DateTime today = DateTime.Today;
 | 
					        private static readonly DateTime today = DateTime.Today;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private static readonly BindableProperty SegmentTypeProperty = Helper.Create<int, RankPage>(nameof(SegmentType), defaultValue: 0, propertyChanged: OnSegmentTypeChanged);
 | 
					        private static readonly BindableProperty SegmentTypeProperty = Helper.Create<int, RankPage>(nameof(SegmentType), defaultValue: 0, propertyChanged: OnSegmentTypeChanged);
 | 
				
			||||||
        private static readonly BindableProperty SegmentDateProperty = Helper.Create<int, RankPage>(nameof(SegmentDate), defaultValue: 0, propertyChanged: OnSegmentDateChanged);
 | 
					        private static readonly BindableProperty SegmentDateProperty = Helper.Create<int, RankPage>(nameof(SegmentDate), defaultValue: 1, propertyChanged: OnSegmentDateChanged);
 | 
				
			||||||
        private static readonly BindableProperty StartDateProperty = Helper.Create<DateTime, RankPage>(nameof(StartDate),
 | 
					        private static readonly BindableProperty StartDateProperty = Helper.Create<DateTime, RankPage>(nameof(StartDate),
 | 
				
			||||||
            defaultValue: today.AddDays(1 - today.Day),
 | 
					            defaultValue: today.AddDays(1 - today.Day),
 | 
				
			||||||
            propertyChanged: OnDateChanged);
 | 
					            propertyChanged: OnDateChanged);
 | 
				
			||||||
@@ -83,7 +87,7 @@ namespace Billing.Views
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            if (!page.isLocked)
 | 
					            if (!page.isLocked)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                page.SegmentDate = -1;
 | 
					                page.SegmentDate = 0;
 | 
				
			||||||
                page.StartDate = @new.Date;
 | 
					                page.StartDate = @new.Date;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -91,7 +95,7 @@ namespace Billing.Views
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            if (!page.isLocked)
 | 
					            if (!page.isLocked)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                page.SegmentDate = -1;
 | 
					                page.SegmentDate = 0;
 | 
				
			||||||
                page.EndDate = @new.Date.LastMoment();
 | 
					                page.EndDate = @new.Date.LastMoment();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -160,6 +164,8 @@ namespace Billing.Views
 | 
				
			|||||||
        public decimal Spending => (decimal)GetValue(SpendingProperty);
 | 
					        public decimal Spending => (decimal)GetValue(SpendingProperty);
 | 
				
			||||||
        public decimal Balance => (decimal)GetValue(BalanceProperty);
 | 
					        public decimal Balance => (decimal)GetValue(BalanceProperty);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public List<string> DateTypes { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public Command LeftCommand { get; }
 | 
					        public Command LeftCommand { get; }
 | 
				
			||||||
        public Command RightCommand { get; }
 | 
					        public Command RightCommand { get; }
 | 
				
			||||||
        public Command FilterCommand { get; }
 | 
					        public Command FilterCommand { get; }
 | 
				
			||||||
@@ -170,11 +176,15 @@ namespace Billing.Views
 | 
				
			|||||||
        private bool isFilterToggled;
 | 
					        private bool isFilterToggled;
 | 
				
			||||||
        private bool isFreezed;
 | 
					        private bool isFreezed;
 | 
				
			||||||
        private bool isLocked;
 | 
					        private bool isLocked;
 | 
				
			||||||
 | 
					        private bool needRefresh = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private const int FILTER_HEIGHT = 100;
 | 
				
			||||||
        private readonly SKTypeface font;
 | 
					        private readonly SKTypeface font;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public RankPage()
 | 
					        public RankPage()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            instance = this;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            LeftCommand = new Command(OnLeftCommand);
 | 
					            LeftCommand = new Command(OnLeftCommand);
 | 
				
			||||||
            RightCommand = new Command(OnRightCommand);
 | 
					            RightCommand = new Command(OnRightCommand);
 | 
				
			||||||
            FilterCommand = new Command(OnFilterCommand);
 | 
					            FilterCommand = new Command(OnFilterCommand);
 | 
				
			||||||
@@ -186,20 +196,41 @@ namespace Billing.Views
 | 
				
			|||||||
                font = style.CreateTypeface(SKFontStyle.Normal);
 | 
					                font = style.CreateTypeface(SKFontStyle.Normal);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            DateTypes = new List<string>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Resource.Custom,
 | 
				
			||||||
 | 
					                Resource.Monthly,
 | 
				
			||||||
 | 
					                Resource.Today,
 | 
				
			||||||
 | 
					                Resource.PastMonth,
 | 
				
			||||||
 | 
					                Resource.PastQuarter,
 | 
				
			||||||
 | 
					                Resource.PastSixMonths,
 | 
				
			||||||
 | 
					                Resource.PastYear,
 | 
				
			||||||
 | 
					                Resource.Total
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            InitializeComponent();
 | 
					            InitializeComponent();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            gridFilter.TranslationY = -60;
 | 
					            gridFilter.TranslationY = -FILTER_HEIGHT;
 | 
				
			||||||
            panelFilter.TranslationY = -60;
 | 
					            panelFilter.TranslationY = -FILTER_HEIGHT;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public override void OnLoaded()
 | 
					        public void SetNeedRefresh()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            needRefresh = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected override void OnAppearing()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (needRefresh)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                needRefresh = false;
 | 
				
			||||||
                OnDateChanged(this);
 | 
					                OnDateChanged(this);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void OnDateTypeCommand(DateType index)
 | 
					        private void OnDateTypeCommand(DateType index)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (index < 0)
 | 
					            if (index < DateType.Monthly || index > DateType.Total)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -251,6 +282,10 @@ namespace Billing.Views
 | 
				
			|||||||
                            max = b.CreateTime;
 | 
					                            max = b.CreateTime;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
 | 
					                    if (min == DateTime.MaxValue && max == DateTime.MinValue)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        return;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                    StartDate = min.Date;
 | 
					                    StartDate = min.Date;
 | 
				
			||||||
                    EndDate = max.Date.LastMoment();
 | 
					                    EndDate = max.Date.LastMoment();
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
@@ -402,9 +437,9 @@ namespace Billing.Views
 | 
				
			|||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                await Task.WhenAll(
 | 
					                await Task.WhenAll(
 | 
				
			||||||
                    gridFilter.TranslateTo(0, -60, easing: Easing.CubicIn),
 | 
					                    gridFilter.TranslateTo(0, -FILTER_HEIGHT, easing: Easing.CubicIn),
 | 
				
			||||||
                    gridFilter.FadeTo(0, easing: Easing.CubicIn),
 | 
					                    gridFilter.FadeTo(0, easing: Easing.CubicIn),
 | 
				
			||||||
                    panelFilter.TranslateTo(0, -60, easing: Easing.CubicIn),
 | 
					                    panelFilter.TranslateTo(0, -FILTER_HEIGHT, easing: Easing.CubicIn),
 | 
				
			||||||
                    panelFilter.FadeTo(0, easing: Easing.CubicIn));
 | 
					                    panelFilter.FadeTo(0, easing: Easing.CubicIn));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -91,6 +91,7 @@
 | 
				
			|||||||
    <Compile Include="Renderers\BillingPageRenderer.cs" />
 | 
					    <Compile Include="Renderers\BillingPageRenderer.cs" />
 | 
				
			||||||
    <Compile Include="Renderers\BlurryPanelRenderer.cs" />
 | 
					    <Compile Include="Renderers\BlurryPanelRenderer.cs" />
 | 
				
			||||||
    <Compile Include="Renderers\SegmentedControlRenderer.cs" />
 | 
					    <Compile Include="Renderers\SegmentedControlRenderer.cs" />
 | 
				
			||||||
 | 
					    <Compile Include="Renderers\OptionPickerRenderer.cs" />
 | 
				
			||||||
  </ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
  <ItemGroup>
 | 
					  <ItemGroup>
 | 
				
			||||||
    <AndroidAsset Include="Assets\fa-brands-400.ttf" />
 | 
					    <AndroidAsset Include="Assets\fa-brands-400.ttf" />
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="utf-8"?>
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="0.8.309" package="org.tsanie.billing" android:installLocation="auto" android:versionCode="8">
 | 
					<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="0.9.311" package="org.tsanie.billing" android:installLocation="auto" android:versionCode="9">
 | 
				
			||||||
	<uses-sdk android:minSdkVersion="24" android:targetSdkVersion="30" />
 | 
						<uses-sdk android:minSdkVersion="24" android:targetSdkVersion="30" />
 | 
				
			||||||
	<application android:label="@string/applabel" android:theme="@style/MainTheme"></application>
 | 
						<application android:label="@string/applabel" android:theme="@style/MainTheme"></application>
 | 
				
			||||||
	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 | 
						<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										29
									
								
								Billing/Billing.Android/Renderers/OptionPickerRenderer.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								Billing/Billing.Android/Renderers/OptionPickerRenderer.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					using Android.Content;
 | 
				
			||||||
 | 
					using Android.Graphics.Drawables;
 | 
				
			||||||
 | 
					using Billing.Droid.Renderers;
 | 
				
			||||||
 | 
					using Billing.UI;
 | 
				
			||||||
 | 
					using Xamarin.Forms;
 | 
				
			||||||
 | 
					using Xamarin.Forms.Platform.Android;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[assembly: ExportRenderer(typeof(OptionPicker), typeof(OptionPickerRenderer))]
 | 
				
			||||||
 | 
					namespace Billing.Droid.Renderers
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class OptionPickerRenderer : PickerRenderer
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public OptionPickerRenderer(Context context) : base(context)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            base.OnElementChanged(e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var control = Control;
 | 
				
			||||||
 | 
					            if (e.NewElement != null && control != null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var drawable = new ColorDrawable(e.NewElement.BackgroundColor.ToAndroid());
 | 
				
			||||||
 | 
					                control.SetBackground(drawable);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -18,10 +18,11 @@ namespace Billing.Droid.Renderers
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            base.OnElementChanged(e);
 | 
					            base.OnElementChanged(e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (e.NewElement != null)
 | 
					            var control = Control;
 | 
				
			||||||
 | 
					            if (e.NewElement != null && control != null)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var drawable = new ColorDrawable(e.NewElement.BackgroundColor.ToAndroid());
 | 
					                var drawable = new ColorDrawable(e.NewElement.BackgroundColor.ToAndroid());
 | 
				
			||||||
                Control.SetBackground(drawable);
 | 
					                control.SetBackground(drawable);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -91,6 +91,7 @@
 | 
				
			|||||||
    <BundleResource Include="Resources\OpenSans-SemiBold.ttf" />
 | 
					    <BundleResource Include="Resources\OpenSans-SemiBold.ttf" />
 | 
				
			||||||
    <Compile Include="Renderers\BlurryPanelRenderer.cs" />
 | 
					    <Compile Include="Renderers\BlurryPanelRenderer.cs" />
 | 
				
			||||||
    <Compile Include="Renderers\SegmentedControlRenderer.cs" />
 | 
					    <Compile Include="Renderers\SegmentedControlRenderer.cs" />
 | 
				
			||||||
 | 
					    <Compile Include="Renderers\OptionPickerRenderer.cs" />
 | 
				
			||||||
  </ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
  <ItemGroup>
 | 
					  <ItemGroup>
 | 
				
			||||||
    <ImageAsset Include="Assets.xcassets\AppIcon.appiconset\Contents.json">
 | 
					    <ImageAsset Include="Assets.xcassets\AppIcon.appiconset\Contents.json">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -44,8 +44,8 @@
 | 
				
			|||||||
	<key>UIFileSharingEnabled</key>
 | 
						<key>UIFileSharingEnabled</key>
 | 
				
			||||||
	<true/>
 | 
						<true/>
 | 
				
			||||||
	<key>CFBundleVersion</key>
 | 
						<key>CFBundleVersion</key>
 | 
				
			||||||
	<string>8</string>
 | 
						<string>9</string>
 | 
				
			||||||
	<key>CFBundleShortVersionString</key>
 | 
						<key>CFBundleShortVersionString</key>
 | 
				
			||||||
	<string>0.8.309</string>
 | 
						<string>0.9.311</string>
 | 
				
			||||||
</dict>
 | 
					</dict>
 | 
				
			||||||
</plist>
 | 
					</plist>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										46
									
								
								Billing/Billing.iOS/Renderers/OptionPickerRenderer.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								Billing/Billing.iOS/Renderers/OptionPickerRenderer.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
				
			|||||||
 | 
					using System.ComponentModel;
 | 
				
			||||||
 | 
					using Billing.iOS.Renderers;
 | 
				
			||||||
 | 
					using Billing.UI;
 | 
				
			||||||
 | 
					using UIKit;
 | 
				
			||||||
 | 
					using Xamarin.Forms;
 | 
				
			||||||
 | 
					using Xamarin.Forms.Platform.iOS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[assembly: ExportRenderer(typeof(OptionPicker), typeof(OptionPickerRenderer))]
 | 
				
			||||||
 | 
					namespace Billing.iOS.Renderers
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public class OptionPickerRenderer : PickerRenderer
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            base.OnElementPropertyChanged(sender, e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (e.PropertyName == nameof(OptionPicker.BorderStyle))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                var control = Control;
 | 
				
			||||||
 | 
					                if (control != null && Element is OptionPicker picker)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    control.BorderStyle = picker.BorderStyle switch
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        BorderStyle.RoundedRect => UITextBorderStyle.RoundedRect,
 | 
				
			||||||
 | 
					                        _ => UITextBorderStyle.None
 | 
				
			||||||
 | 
					                    };
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            base.OnElementChanged(e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var control = Control;
 | 
				
			||||||
 | 
					            if (control != null && e.NewElement is OptionPicker picker)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                control.BorderStyle = picker.BorderStyle switch
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    BorderStyle.RoundedRect => UITextBorderStyle.RoundedRect,
 | 
				
			||||||
 | 
					                    _ => UITextBorderStyle.None
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user