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
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
@@ -214,50 +214,50 @@
CornerRadius="{TemplateBinding CornerRadius}">
-
+
-
-
-
-
-
-
-
-
-
-
-
-
@@ -272,12 +272,12 @@
Color="{DynamicResource ThemeAccentColor}" />
-
-
-
-
-