diff --git a/samples/ControlCatalog/Converter/HexConverter.cs b/samples/ControlCatalog/Converter/HexConverter.cs index 83a52212f6..31cce5ba67 100644 --- a/samples/ControlCatalog/Converter/HexConverter.cs +++ b/samples/ControlCatalog/Converter/HexConverter.cs @@ -7,7 +7,7 @@ namespace ControlCatalog.Converter; public class HexConverter : IValueConverter { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { var str = value?.ToString(); if (str == null) @@ -18,7 +18,7 @@ public class HexConverter : IValueConverter } - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) { try { diff --git a/src/Avalonia.Base/Layout/LayoutHelper.cs b/src/Avalonia.Base/Layout/LayoutHelper.cs index 404d19906a..0851dbaea9 100644 --- a/src/Avalonia.Base/Layout/LayoutHelper.cs +++ b/src/Avalonia.Base/Layout/LayoutHelper.cs @@ -251,6 +251,17 @@ namespace Avalonia.Layout { double newValue; + // Round the value to avoid FP errors. This is needed because if `value` has a floating + // point precision error (e.g. 79.333333333333343) then when it's multiplied by + // `dpiScale` and rounded up, it will be rounded up to a value one greater than it + // should be. +#if NET6_0_OR_GREATER + value = Math.Round(value, 8, MidpointRounding.ToZero); +#else + // MidpointRounding.ToZero isn't available in netstandard2.0. + value = Math.Truncate(value * 1e8) / 1e8; +#endif + // If DPI == 1, don't use DPI-aware rounding. if (!MathUtilities.IsOne(dpiScale)) { diff --git a/src/Avalonia.Controls.ColorPicker/Converters/DoNothingForNullConverter.cs b/src/Avalonia.Controls.ColorPicker/Converters/DoNothingForNullConverter.cs new file mode 100644 index 0000000000..421a5acb28 --- /dev/null +++ b/src/Avalonia.Controls.ColorPicker/Converters/DoNothingForNullConverter.cs @@ -0,0 +1,35 @@ +using System; +using System.Globalization; +using Avalonia.Data; +using Avalonia.Data.Converters; + +namespace Avalonia.Controls.Converters +{ + /// + /// Converter that will do nothing (not update bound values) when a null value is encountered. + /// This converter enables binding nullable with non-nullable properties in some scenarios. + /// + public class DoNothingForNullConverter : IValueConverter + { + /// + public object? Convert( + object? value, + Type targetType, + object? parameter, + CultureInfo culture) + { + return value ?? BindingOperations.DoNothing; + } + + /// + public object? ConvertBack( + object? value, + Type targetType, + object? parameter, + CultureInfo culture) + { + return value ?? BindingOperations.DoNothing; + } + } +} + diff --git a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml index 59cc48975f..dab4142001 100644 --- a/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml +++ b/src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml @@ -11,6 +11,7 @@ + 48 30 @@ -205,7 +206,7 @@ diff --git a/src/Avalonia.Controls.DataGrid/DataGridRowGroupHeader.cs b/src/Avalonia.Controls.DataGrid/DataGridRowGroupHeader.cs index d63c738133..69e6766bfd 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridRowGroupHeader.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridRowGroupHeader.cs @@ -23,10 +23,10 @@ namespace Avalonia.Controls [PseudoClasses(":pressed", ":current", ":expanded")] public class DataGridRowGroupHeader : TemplatedControl { - private const string DATAGRIDROWGROUPHEADER_expanderButton = "ExpanderButton"; - private const string DATAGRIDROWGROUPHEADER_indentSpacer = "IndentSpacer"; - private const string DATAGRIDROWGROUPHEADER_itemCountElement = "ItemCountElement"; - private const string DATAGRIDROWGROUPHEADER_propertyNameElement = "PropertyNameElement"; + private const string DATAGRIDROWGROUPHEADER_expanderButton = "PART_ExpanderButton"; + private const string DATAGRIDROWGROUPHEADER_indentSpacer = "PART_IndentSpacer"; + private const string DATAGRIDROWGROUPHEADER_itemCountElement = "PART_ItemCountElement"; + private const string DATAGRIDROWGROUPHEADER_propertyNameElement = "PART_PropertyNameElement"; private bool _areIsCheckedHandlersSuspended; private ToggleButton _expanderButton; diff --git a/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml b/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml index 364a2a52e3..b4bae02b9b 100644 --- a/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml +++ b/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml @@ -409,9 +409,9 @@ ColumnDefinitions="Auto,Auto,Auto,Auto,*" RowDefinitions="*,Auto"> - - - - diff --git a/src/Avalonia.Controls.DataGrid/Themes/Simple.xaml b/src/Avalonia.Controls.DataGrid/Themes/Simple.xaml index 6a748f399e..b43addff86 100644 --- a/src/Avalonia.Controls.DataGrid/Themes/Simple.xaml +++ b/src/Avalonia.Controls.DataGrid/Themes/Simple.xaml @@ -258,10 +258,10 @@ ColumnDefinitions="Auto,Auto,Auto,Auto" RowDefinitions="Auto,*,Auto"> - - - - diff --git a/src/Avalonia.Controls/Calendar/Calendar.cs b/src/Avalonia.Controls/Calendar/Calendar.cs index bb838a4f3f..0de068a416 100644 --- a/src/Avalonia.Controls/Calendar/Calendar.cs +++ b/src/Avalonia.Controls/Calendar/Calendar.cs @@ -2109,8 +2109,8 @@ namespace Avalonia.Controls RemovedItems = new Collection(); } - private const string PART_ElementRoot = "Root"; - private const string PART_ElementMonth = "CalendarItem"; + private const string PART_ElementRoot = "PART_Root"; + private const string PART_ElementMonth = "PART_CalendarItem"; /// /// Builds the visual tree for the diff --git a/src/Avalonia.Controls/Calendar/CalendarItem.cs b/src/Avalonia.Controls/Calendar/CalendarItem.cs index 75e9f52621..e2eabb5f28 100644 --- a/src/Avalonia.Controls/Calendar/CalendarItem.cs +++ b/src/Avalonia.Controls/Calendar/CalendarItem.cs @@ -32,11 +32,11 @@ namespace Avalonia.Controls.Primitives /// private const int NumberOfDaysPerWeek = 7; - private const string PART_ElementHeaderButton = "HeaderButton"; - private const string PART_ElementPreviousButton = "PreviousButton"; - private const string PART_ElementNextButton = "NextButton"; - private const string PART_ElementMonthView = "MonthView"; - private const string PART_ElementYearView = "YearView"; + private const string PART_ElementHeaderButton = "PART_HeaderButton"; + private const string PART_ElementPreviousButton = "PART_PreviousButton"; + private const string PART_ElementNextButton = "PART_NextButton"; + private const string PART_ElementMonthView = "PART_MonthView"; + private const string PART_ElementYearView = "PART_YearView"; private Button? _headerButton; private Button? _nextButton; diff --git a/src/Avalonia.Controls/DateTimePickers/DatePicker.cs b/src/Avalonia.Controls/DateTimePickers/DatePicker.cs index f2b808fe0d..fb27feb521 100644 --- a/src/Avalonia.Controls/DateTimePickers/DatePicker.cs +++ b/src/Avalonia.Controls/DateTimePickers/DatePicker.cs @@ -14,15 +14,15 @@ namespace Avalonia.Controls /// /// A control to allow the user to select a date /// - [TemplatePart("ButtonContentGrid", typeof(Grid))] - [TemplatePart("DayText", typeof(TextBlock))] - [TemplatePart("FirstSpacer", typeof(Rectangle))] - [TemplatePart("FlyoutButton", typeof(Button))] - [TemplatePart("MonthText", typeof(TextBlock))] - [TemplatePart("PickerPresenter", typeof(DatePickerPresenter))] - [TemplatePart("Popup", typeof(Popup))] - [TemplatePart("SecondSpacer", typeof(Rectangle))] - [TemplatePart("YearText", typeof(TextBlock))] + [TemplatePart("PART_ButtonContentGrid", typeof(Grid))] + [TemplatePart("PART_DayTextBlock", typeof(TextBlock))] + [TemplatePart("PART_FirstSpacer", typeof(Rectangle))] + [TemplatePart("PART_FlyoutButton", typeof(Button))] + [TemplatePart("PART_MonthTextBlock", typeof(TextBlock))] + [TemplatePart("PART_PickerPresenter", typeof(DatePickerPresenter))] + [TemplatePart("PART_Popup", typeof(Popup))] + [TemplatePart("PART_SecondSpacer", typeof(Rectangle))] + [TemplatePart("PART_YearTextBlock", typeof(TextBlock))] [PseudoClasses(":hasnodate")] public class DatePicker : TemplatedControl { @@ -280,15 +280,15 @@ namespace Avalonia.Controls } base.OnApplyTemplate(e); - _flyoutButton = e.NameScope.Find - - - + @@ -181,62 +181,62 @@ Padding="{DynamicResource DateTimeFlyoutBorderPadding}" MaxHeight="398" CornerRadius="{TemplateBinding CornerRadius}"> - + - + - - - + + - + - - - + + - + - - - + + - - - + @@ -244,7 +244,7 @@ VerticalAlignment="Top" Fill="{DynamicResource DatePickerFlyoutPresenterSpacerFill}" Grid.ColumnSpan="2"/> - - - - + @@ -209,42 +209,42 @@ Padding="{DynamicResource DateTimeFlyoutBorderPadding}" MaxHeight="398"> - + - + - - - + + - + - - - + + - + - - - + + - - - - - - - + @@ -197,50 +197,50 @@ CornerRadius="{TemplateBinding CornerRadius}"> - + - + - - - - + - - - - + - - - - - - - - - + @@ -214,50 +214,50 @@ CornerRadius="{TemplateBinding CornerRadius}"> - + - - - - - - - - - - - - @@ -272,12 +272,12 @@ Color="{DynamicResource ThemeAccentColor}" /> - - - -