Browse Source

Merge branch 'master' into improve-treeview-navigation

pull/8890/head
Max Katz 4 years ago
committed by GitHub
parent
commit
f61c09ac0c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      samples/ControlCatalog/Converter/HexConverter.cs
  2. 11
      src/Avalonia.Base/Layout/LayoutHelper.cs
  3. 35
      src/Avalonia.Controls.ColorPicker/Converters/DoNothingForNullConverter.cs
  4. 3
      src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml
  5. 8
      src/Avalonia.Controls.DataGrid/DataGridRowGroupHeader.cs
  6. 8
      src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml
  7. 8
      src/Avalonia.Controls.DataGrid/Themes/Simple.xaml
  8. 4
      src/Avalonia.Controls/Calendar/Calendar.cs
  9. 10
      src/Avalonia.Controls/Calendar/CalendarItem.cs
  10. 36
      src/Avalonia.Controls/DateTimePickers/DatePicker.cs
  11. 68
      src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs
  12. 48
      src/Avalonia.Controls/DateTimePickers/TimePicker.cs
  13. 56
      src/Avalonia.Controls/DateTimePickers/TimePickerPresenter.cs
  14. 10
      src/Avalonia.Controls/ToggleSwitch.cs
  15. 2
      src/Avalonia.Controls/Utils/BorderRenderHelper.cs
  16. 8
      src/Avalonia.Dialogs/ManagedFileChooser.cs
  17. 4
      src/Avalonia.Themes.Fluent/Controls/Calendar.xaml
  18. 10
      src/Avalonia.Themes.Fluent/Controls/CalendarItem.xaml
  19. 56
      src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml
  20. 4
      src/Avalonia.Themes.Fluent/Controls/ManagedFileChooser.xaml
  21. 60
      src/Avalonia.Themes.Fluent/Controls/TimePicker.xaml
  22. 4
      src/Avalonia.Themes.Fluent/Controls/ToggleSwitch.xaml
  23. 4
      src/Avalonia.Themes.Simple/Controls/Calendar.xaml
  24. 10
      src/Avalonia.Themes.Simple/Controls/CalendarItem.xaml
  25. 52
      src/Avalonia.Themes.Simple/Controls/DatePicker.xaml
  26. 4
      src/Avalonia.Themes.Simple/Controls/ManagedFileChooser.xaml
  27. 58
      src/Avalonia.Themes.Simple/Controls/TimePicker.xaml
  28. 4
      src/Avalonia.Themes.Simple/Controls/ToggleSwitch.xaml
  29. 64
      src/tools/DevAnalyzers/OnPropertyChangedOverrideAnalyzer.cs
  30. 7
      src/tools/DevGenerators/CompositionGenerator/CompositionRoslynGenerator.cs
  31. 30
      src/tools/DevGenerators/CompositionGenerator/Extensions.cs
  32. 4
      src/tools/DevGenerators/CompositionGenerator/Generator.Utils.cs
  33. 16
      src/tools/DevGenerators/CompositionGenerator/Generator.cs
  34. 1
      src/tools/DevGenerators/DevGenerators.csproj
  35. 11
      src/tools/DevGenerators/GetProcAddressInitialization.cs
  36. 57
      tests/Avalonia.Controls.UnitTests/BorderTests.cs
  37. 26
      tests/Avalonia.Controls.UnitTests/DatePickerTests.cs
  38. 20
      tests/Avalonia.Controls.UnitTests/TimePickerTests.cs

4
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
{

11
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))
{

35
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
{
/// <summary>
/// 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.
/// </summary>
public class DoNothingForNullConverter : IValueConverter
{
/// <inheritdoc/>
public object? Convert(
object? value,
Type targetType,
object? parameter,
CultureInfo culture)
{
return value ?? BindingOperations.DoNothing;
}
/// <inheritdoc/>
public object? ConvertBack(
object? value,
Type targetType,
object? parameter,
CultureInfo culture)
{
return value ?? BindingOperations.DoNothing;
}
}
}

3
src/Avalonia.Controls.ColorPicker/Themes/Fluent/ColorView.xaml

@ -11,6 +11,7 @@
<pc:ThirdComponentConverter x:Key="ThirdComponentConverter" />
<converters:ColorToDisplayNameConverter x:Key="ColorToDisplayNameConverter" />
<converters:ColorToHexConverter x:Key="ColorToHexConverter" />
<converters:DoNothingForNullConverter x:Key="DoNothingForNullConverter" />
<globalization:NumberFormatInfo x:Key="ColorViewComponentNumberFormat" NumberDecimalDigits="0" />
<x:Double x:Key="ColorViewTabStripHeight">48</x:Double>
<x:Double x:Key="ColorViewComponentLabelWidth">30</x:Double>
@ -205,7 +206,7 @@
</Border>
</TabItem.Header>
<ListBox Items="{TemplateBinding PaletteColors}"
SelectedItem="{Binding Color, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
SelectedItem="{Binding Color, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource DoNothingForNullConverter}, Mode=TwoWay}"
UseLayoutRounding="False"
Margin="12">
<ListBox.Styles>

8
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;

8
src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml

@ -409,9 +409,9 @@
ColumnDefinitions="Auto,Auto,Auto,Auto,*"
RowDefinitions="*,Auto">
<Rectangle Name="IndentSpacer"
<Rectangle Name="PART_IndentSpacer"
Grid.Column="1" />
<ToggleButton Name="ExpanderButton"
<ToggleButton Name="PART_ExpanderButton"
Grid.Column="2"
Width="12"
Height="12"
@ -428,14 +428,14 @@
Orientation="Horizontal"
VerticalAlignment="Center"
Margin="12,0,0,0">
<TextBlock Name="PropertyNameElement"
<TextBlock Name="PART_PropertyNameElement"
Margin="4,0,0,0"
IsVisible="{TemplateBinding IsPropertyNameVisible}"
Foreground="{TemplateBinding Foreground}" />
<TextBlock Margin="4,0,0,0"
Text="{ReflectionBinding Key}"
Foreground="{TemplateBinding Foreground}" />
<TextBlock Name="ItemCountElement"
<TextBlock Name="PART_ItemCountElement"
Margin="4,0,0,0"
IsVisible="{TemplateBinding IsItemCountVisible}"
Foreground="{TemplateBinding Foreground}" />

8
src/Avalonia.Controls.DataGrid/Themes/Simple.xaml

@ -258,10 +258,10 @@
ColumnDefinitions="Auto,Auto,Auto,Auto"
RowDefinitions="Auto,*,Auto">
<Rectangle Name="IndentSpacer"
<Rectangle Name="PART_IndentSpacer"
Grid.Row="1"
Grid.Column="1" />
<ToggleButton Name="ExpanderButton"
<ToggleButton Name="PART_ExpanderButton"
Grid.Row="1"
Grid.Column="2"
Margin="2,0,0,0"
@ -277,12 +277,12 @@
Margin="0,1,0,1"
VerticalAlignment="Center"
Orientation="Horizontal">
<TextBlock Name="PropertyNameElement"
<TextBlock Name="PART_PropertyNameElement"
Margin="4,0,0,0"
IsVisible="{TemplateBinding IsPropertyNameVisible}" />
<TextBlock Margin="4,0,0,0"
Text="{Binding Key}" />
<TextBlock Name="ItemCountElement"
<TextBlock Name="PART_ItemCountElement"
Margin="4,0,0,0"
IsVisible="{TemplateBinding IsItemCountVisible}" />
</StackPanel>

4
src/Avalonia.Controls/Calendar/Calendar.cs

@ -2109,8 +2109,8 @@ namespace Avalonia.Controls
RemovedItems = new Collection<DateTime>();
}
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";
/// <summary>
/// Builds the visual tree for the

10
src/Avalonia.Controls/Calendar/CalendarItem.cs

@ -32,11 +32,11 @@ namespace Avalonia.Controls.Primitives
/// </summary>
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;

36
src/Avalonia.Controls/DateTimePickers/DatePicker.cs

@ -14,15 +14,15 @@ namespace Avalonia.Controls
/// <summary>
/// A control to allow the user to select a date
/// </summary>
[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<Button>("FlyoutButton");
_dayText = e.NameScope.Find<TextBlock>("DayText");
_monthText = e.NameScope.Find<TextBlock>("MonthText");
_yearText = e.NameScope.Find<TextBlock>("YearText");
_container = e.NameScope.Find<Grid>("ButtonContentGrid");
_spacer1 = e.NameScope.Find<Rectangle>("FirstSpacer");
_spacer2 = e.NameScope.Find<Rectangle>("SecondSpacer");
_popup = e.NameScope.Find<Popup>("Popup");
_presenter = e.NameScope.Find<DatePickerPresenter>("PickerPresenter");
_flyoutButton = e.NameScope.Find<Button>("PART_FlyoutButton");
_dayText = e.NameScope.Find<TextBlock>("PART_DayTextBlock");
_monthText = e.NameScope.Find<TextBlock>("PART_MonthTextBlock");
_yearText = e.NameScope.Find<TextBlock>("PART_YearTextBlock");
_container = e.NameScope.Find<Grid>("PART_ButtonContentGrid");
_spacer1 = e.NameScope.Find<Rectangle>("PART_FirstSpacer");
_spacer2 = e.NameScope.Find<Rectangle>("PART_SecondSpacer");
_popup = e.NameScope.Find<Popup>("PART_Popup");
_presenter = e.NameScope.Find<DatePickerPresenter>("PART_PickerPresenter");
_areControlsAvailable = true;

68
src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs

@ -13,23 +13,23 @@ namespace Avalonia.Controls
/// Defines the presenter used for selecting a date for a
/// <see cref="DatePicker"/>
/// </summary>
[TemplatePart("AcceptButton", typeof(Button))]
[TemplatePart("DayDownButton", typeof(RepeatButton))]
[TemplatePart("DayHost", typeof(Panel))]
[TemplatePart("DaySelector", typeof(DateTimePickerPanel))]
[TemplatePart("DayUpButton", typeof(RepeatButton))]
[TemplatePart("DismissButton", typeof(Button))]
[TemplatePart("FirstSpacer", typeof(Rectangle))]
[TemplatePart("MonthDownButton", typeof(RepeatButton))]
[TemplatePart("MonthHost", typeof(Panel))]
[TemplatePart("MonthSelector", typeof(DateTimePickerPanel))]
[TemplatePart("MonthUpButton", typeof(RepeatButton))]
[TemplatePart("PickerContainer", typeof(Grid))]
[TemplatePart("SecondSpacer", typeof(Rectangle))]
[TemplatePart("YearDownButton", typeof(RepeatButton))]
[TemplatePart("YearHost", typeof(Panel))]
[TemplatePart("YearSelector", typeof(DateTimePickerPanel))]
[TemplatePart("YearUpButton", typeof(RepeatButton))]
[TemplatePart("PART_AcceptButton", typeof(Button))]
[TemplatePart("PART_DayDownButton", typeof(RepeatButton))]
[TemplatePart("PART_DayHost", typeof(Panel))]
[TemplatePart("PART_DaySelector", typeof(DateTimePickerPanel))]
[TemplatePart("PART_DayUpButton", typeof(RepeatButton))]
[TemplatePart("PART_DismissButton", typeof(Button))]
[TemplatePart("PART_FirstSpacer", typeof(Rectangle))]
[TemplatePart("PART_MonthDownButton", typeof(RepeatButton))]
[TemplatePart("PART_MonthHost", typeof(Panel))]
[TemplatePart("PART_MonthSelector", typeof(DateTimePickerPanel))]
[TemplatePart("PART_MonthUpButton", typeof(RepeatButton))]
[TemplatePart("PART_PickerContainer", typeof(Grid))]
[TemplatePart("PART_SecondSpacer", typeof(Rectangle))]
[TemplatePart("PART_YearDownButton", typeof(RepeatButton))]
[TemplatePart("PART_YearHost", typeof(Panel))]
[TemplatePart("PART_YearSelector", typeof(DateTimePickerPanel))]
[TemplatePart("PART_YearUpButton", typeof(RepeatButton))]
public class DatePickerPresenter : PickerPresenterBase
{
/// <summary>
@ -253,58 +253,58 @@ namespace Avalonia.Controls
{
base.OnApplyTemplate(e);
// These are requirements, so throw if not found
_pickerContainer = e.NameScope.Get<Grid>("PickerContainer");
_monthHost = e.NameScope.Get<Panel>("MonthHost");
_dayHost = e.NameScope.Get<Panel>("DayHost");
_yearHost = e.NameScope.Get<Panel>("YearHost");
_pickerContainer = e.NameScope.Get<Grid>("PART_PickerContainer");
_monthHost = e.NameScope.Get<Panel>("PART_MonthHost");
_dayHost = e.NameScope.Get<Panel>("PART_DayHost");
_yearHost = e.NameScope.Get<Panel>("PART_YearHost");
_monthSelector = e.NameScope.Get<DateTimePickerPanel>("MonthSelector");
_monthSelector = e.NameScope.Get<DateTimePickerPanel>("PART_MonthSelector");
_monthSelector.SelectionChanged += OnMonthChanged;
_daySelector = e.NameScope.Get<DateTimePickerPanel>("DaySelector");
_daySelector = e.NameScope.Get<DateTimePickerPanel>("PART_DaySelector");
_daySelector.SelectionChanged += OnDayChanged;
_yearSelector = e.NameScope.Get<DateTimePickerPanel>("YearSelector");
_yearSelector = e.NameScope.Get<DateTimePickerPanel>("PART_YearSelector");
_yearSelector.SelectionChanged += OnYearChanged;
_acceptButton = e.NameScope.Get<Button>("AcceptButton");
_acceptButton = e.NameScope.Get<Button>("PART_AcceptButton");
_monthUpButton = e.NameScope.Find<RepeatButton>("MonthUpButton");
_monthUpButton = e.NameScope.Find<RepeatButton>("PART_MonthUpButton");
if (_monthUpButton != null)
{
_monthUpButton.Click += OnSelectorButtonClick;
}
_monthDownButton = e.NameScope.Find<RepeatButton>("MonthDownButton");
_monthDownButton = e.NameScope.Find<RepeatButton>("PART_MonthDownButton");
if (_monthDownButton != null)
{
_monthDownButton.Click += OnSelectorButtonClick;
}
_dayUpButton = e.NameScope.Find<RepeatButton>("DayUpButton");
_dayUpButton = e.NameScope.Find<RepeatButton>("PART_DayUpButton");
if (_dayUpButton != null)
{
_dayUpButton.Click += OnSelectorButtonClick;
}
_dayDownButton = e.NameScope.Find<RepeatButton>("DayDownButton");
_dayDownButton = e.NameScope.Find<RepeatButton>("PART_DayDownButton");
if (_dayDownButton != null)
{
_dayDownButton.Click += OnSelectorButtonClick;
}
_yearUpButton = e.NameScope.Find<RepeatButton>("YearUpButton");
_yearUpButton = e.NameScope.Find<RepeatButton>("PART_YearUpButton");
if (_yearUpButton != null)
{
_yearUpButton.Click += OnSelectorButtonClick;
}
_yearDownButton = e.NameScope.Find<RepeatButton>("YearDownButton");
_yearDownButton = e.NameScope.Find<RepeatButton>("PART_YearDownButton");
if (_yearDownButton != null)
{
_yearDownButton.Click += OnSelectorButtonClick;
}
_dismissButton = e.NameScope.Find<Button>("DismissButton");
_spacer1 = e.NameScope.Find<Rectangle>("FirstSpacer");
_spacer2 = e.NameScope.Find<Rectangle>("SecondSpacer");
_dismissButton = e.NameScope.Find<Button>("PART_DismissButton");
_spacer1 = e.NameScope.Find<Rectangle>("PART_FirstSpacer");
_spacer2 = e.NameScope.Find<Rectangle>("PART_SecondSpacer");
if (_acceptButton != null)
{

48
src/Avalonia.Controls/DateTimePickers/TimePicker.cs

@ -12,18 +12,18 @@ namespace Avalonia.Controls
/// <summary>
/// A control to allow the user to select a time.
/// </summary>
[TemplatePart("FirstColumnDivider", typeof(Rectangle))]
[TemplatePart("FirstPickerHost", typeof(Border))]
[TemplatePart("FlyoutButton", typeof(Button))]
[TemplatePart("FlyoutButtonContentGrid", typeof(Grid))]
[TemplatePart("HourTextBlock", typeof(TextBlock))]
[TemplatePart("MinuteTextBlock", typeof(TextBlock))]
[TemplatePart("PeriodTextBlock", typeof(TextBlock))]
[TemplatePart("PickerPresenter", typeof(TimePickerPresenter))]
[TemplatePart("Popup", typeof(Popup))]
[TemplatePart("SecondColumnDivider", typeof(Rectangle))]
[TemplatePart("SecondPickerHost", typeof(Border))]
[TemplatePart("ThirdPickerHost", typeof(Border))]
[TemplatePart("PART_FirstColumnDivider", typeof(Rectangle))]
[TemplatePart("PART_FirstPickerHost", typeof(Border))]
[TemplatePart("PART_FlyoutButton", typeof(Button))]
[TemplatePart("PART_FlyoutButtonContentGrid", typeof(Grid))]
[TemplatePart("PART_HourTextBlock", typeof(TextBlock))]
[TemplatePart("PART_MinuteTextBlock", typeof(TextBlock))]
[TemplatePart("PART_PeriodTextBlock", typeof(TextBlock))]
[TemplatePart("PART_PickerPresenter", typeof(TimePickerPresenter))]
[TemplatePart("PART_Popup", typeof(Popup))]
[TemplatePart("PART_SecondColumnDivider", typeof(Rectangle))]
[TemplatePart("PART_SecondPickerHost", typeof(Border))]
[TemplatePart("PART_ThirdPickerHost", typeof(Border))]
[PseudoClasses(":hasnotime")]
public class TimePicker : TemplatedControl
{
@ -169,23 +169,23 @@ namespace Avalonia.Controls
}
base.OnApplyTemplate(e);
_flyoutButton = e.NameScope.Find<Button>("FlyoutButton");
_flyoutButton = e.NameScope.Find<Button>("PART_FlyoutButton");
_firstPickerHost = e.NameScope.Find<Border>("FirstPickerHost");
_secondPickerHost = e.NameScope.Find<Border>("SecondPickerHost");
_thirdPickerHost = e.NameScope.Find<Border>("ThirdPickerHost");
_firstPickerHost = e.NameScope.Find<Border>("PART_FirstPickerHost");
_secondPickerHost = e.NameScope.Find<Border>("PART_SecondPickerHost");
_thirdPickerHost = e.NameScope.Find<Border>("PART_ThirdPickerHost");
_hourText = e.NameScope.Find<TextBlock>("HourTextBlock");
_minuteText = e.NameScope.Find<TextBlock>("MinuteTextBlock");
_periodText = e.NameScope.Find<TextBlock>("PeriodTextBlock");
_hourText = e.NameScope.Find<TextBlock>("PART_HourTextBlock");
_minuteText = e.NameScope.Find<TextBlock>("PART_MinuteTextBlock");
_periodText = e.NameScope.Find<TextBlock>("PART_PeriodTextBlock");
_firstSplitter = e.NameScope.Find<Rectangle>("FirstColumnDivider");
_secondSplitter = e.NameScope.Find<Rectangle>("SecondColumnDivider");
_firstSplitter = e.NameScope.Find<Rectangle>("PART_FirstColumnDivider");
_secondSplitter = e.NameScope.Find<Rectangle>("PART_SecondColumnDivider");
_contentGrid = e.NameScope.Find<Grid>("FlyoutButtonContentGrid");
_contentGrid = e.NameScope.Find<Grid>("PART_FlyoutButtonContentGrid");
_popup = e.NameScope.Find<Popup>("Popup");
_presenter = e.NameScope.Find<TimePickerPresenter>("PickerPresenter");
_popup = e.NameScope.Find<Popup>("PART_Popup");
_presenter = e.NameScope.Find<TimePickerPresenter>("PART_PickerPresenter");
if (_flyoutButton != null)
_flyoutButton.Click += OnFlyoutButtonClicked;

56
src/Avalonia.Controls/DateTimePickers/TimePickerPresenter.cs

@ -11,20 +11,20 @@ namespace Avalonia.Controls
/// Defines the presenter used for selecting a time. Intended for use with
/// <see cref="TimePicker"/> but can be used independently
/// </summary>
[TemplatePart("AcceptButton", typeof(Button))]
[TemplatePart("DismissButton", typeof(Button))]
[TemplatePart("HourDownButton", typeof(RepeatButton))]
[TemplatePart("HourSelector", typeof(DateTimePickerPanel))]
[TemplatePart("HourUpButton", typeof(RepeatButton))]
[TemplatePart("MinuteDownButton", typeof(RepeatButton))]
[TemplatePart("MinuteSelector", typeof(DateTimePickerPanel))]
[TemplatePart("MinuteUpButton", typeof(RepeatButton))]
[TemplatePart("PeriodDownButton", typeof(RepeatButton))]
[TemplatePart("PeriodHost", typeof(Panel))]
[TemplatePart("PeriodSelector", typeof(DateTimePickerPanel))]
[TemplatePart("PeriodUpButton", typeof(RepeatButton))]
[TemplatePart("PickerContainer", typeof(Grid))]
[TemplatePart("SecondSpacer", typeof(Rectangle))]
[TemplatePart("PART_AcceptButton", typeof(Button))]
[TemplatePart("PART_DismissButton", typeof(Button))]
[TemplatePart("PART_HourDownButton", typeof(RepeatButton))]
[TemplatePart("PART_HourSelector", typeof(DateTimePickerPanel))]
[TemplatePart("PART_HourUpButton", typeof(RepeatButton))]
[TemplatePart("PART_MinuteDownButton", typeof(RepeatButton))]
[TemplatePart("PART_MinuteSelector", typeof(DateTimePickerPanel))]
[TemplatePart("PART_MinuteUpButton", typeof(RepeatButton))]
[TemplatePart("PART_PeriodDownButton", typeof(RepeatButton))]
[TemplatePart("PART_PeriodHost", typeof(Panel))]
[TemplatePart("PART_PeriodSelector", typeof(DateTimePickerPanel))]
[TemplatePart("PART_PeriodUpButton", typeof(RepeatButton))]
[TemplatePart("PART_PickerContainer", typeof(Grid))]
[TemplatePart("PART_SecondSpacer", typeof(Rectangle))]
public class TimePickerPresenter : PickerPresenterBase
{
/// <summary>
@ -122,40 +122,40 @@ namespace Avalonia.Controls
{
base.OnApplyTemplate(e);
_pickerContainer = e.NameScope.Get<Grid>("PickerContainer");
_periodHost = e.NameScope.Get<Panel>("PeriodHost");
_pickerContainer = e.NameScope.Get<Grid>("PART_PickerContainer");
_periodHost = e.NameScope.Get<Panel>("PART_PeriodHost");
_hourSelector = e.NameScope.Get<DateTimePickerPanel>("HourSelector");
_minuteSelector = e.NameScope.Get<DateTimePickerPanel>("MinuteSelector");
_periodSelector = e.NameScope.Get<DateTimePickerPanel>("PeriodSelector");
_hourSelector = e.NameScope.Get<DateTimePickerPanel>("PART_HourSelector");
_minuteSelector = e.NameScope.Get<DateTimePickerPanel>("PART_MinuteSelector");
_periodSelector = e.NameScope.Get<DateTimePickerPanel>("PART_PeriodSelector");
_spacer2 = e.NameScope.Get<Rectangle>("SecondSpacer");
_spacer2 = e.NameScope.Get<Rectangle>("PART_SecondSpacer");
_acceptButton = e.NameScope.Get<Button>("AcceptButton");
_acceptButton = e.NameScope.Get<Button>("PART_AcceptButton");
_acceptButton.Click += OnAcceptButtonClicked;
_hourUpButton = e.NameScope.Find<RepeatButton>("HourUpButton");
_hourUpButton = e.NameScope.Find<RepeatButton>("PART_HourUpButton");
if (_hourUpButton != null)
_hourUpButton.Click += OnSelectorButtonClick;
_hourDownButton = e.NameScope.Find<RepeatButton>("HourDownButton");
_hourDownButton = e.NameScope.Find<RepeatButton>("PART_HourDownButton");
if (_hourDownButton != null)
_hourDownButton.Click += OnSelectorButtonClick;
_minuteUpButton = e.NameScope.Find<RepeatButton>("MinuteUpButton");
_minuteUpButton = e.NameScope.Find<RepeatButton>("PART_MinuteUpButton");
if (_minuteUpButton != null)
_minuteUpButton.Click += OnSelectorButtonClick;
_minuteDownButton = e.NameScope.Find<RepeatButton>("MinuteDownButton");
_minuteDownButton = e.NameScope.Find<RepeatButton>("PART_MinuteDownButton");
if (_minuteDownButton != null)
_minuteDownButton.Click += OnSelectorButtonClick;
_periodUpButton = e.NameScope.Find<RepeatButton>("PeriodUpButton");
_periodUpButton = e.NameScope.Find<RepeatButton>("PART_PeriodUpButton");
if (_periodUpButton != null)
_periodUpButton.Click += OnSelectorButtonClick;
_periodDownButton = e.NameScope.Find<RepeatButton>("PeriodDownButton");
_periodDownButton = e.NameScope.Find<RepeatButton>("PART_PeriodDownButton");
if (_periodDownButton != null)
_periodDownButton.Click += OnSelectorButtonClick;
_dismissButton = e.NameScope.Find<Button>("DismissButton");
_dismissButton = e.NameScope.Find<Button>("PART_DismissButton");
if (_dismissButton != null)
_dismissButton.Click += OnDismissButtonClicked;

10
src/Avalonia.Controls/ToggleSwitch.cs

@ -9,8 +9,10 @@ namespace Avalonia.Controls
/// <summary>
/// A Toggle Switch control.
/// </summary>
[TemplatePart("MovingKnobs", typeof(Panel))]
[TemplatePart("SwitchKnob", typeof(Panel))]
[TemplatePart("PART_MovingKnobs", typeof(Panel))]
[TemplatePart("PART_OffContentPresenter", typeof(ContentPresenter))]
[TemplatePart("PART_OnContentPresenter", typeof(ContentPresenter))]
[TemplatePart("PART_SwitchKnob", typeof(Panel))]
[PseudoClasses(":dragging")]
public class ToggleSwitch : ToggleButton
{
@ -163,8 +165,8 @@ namespace Avalonia.Controls
{
base.OnApplyTemplate(e);
_switchKnob = e.NameScope.Find<Panel>("SwitchKnob");
_knobsPanel = e.NameScope.Get<Panel>("MovingKnobs");
_switchKnob = e.NameScope.Find<Panel>("PART_SwitchKnob");
_knobsPanel = e.NameScope.Get<Panel>("PART_MovingKnobs");
_knobsPanel.PointerPressed += KnobsPanel_PointerPressed;
_knobsPanel.PointerReleased += KnobsPanel_PointerReleased;

2
src/Avalonia.Controls/Utils/BorderRenderHelper.cs

@ -61,7 +61,7 @@ namespace Avalonia.Controls.Utils
_backgroundGeometryCache = null;
}
if (boundRect.Width != 0 && innerRect.Height != 0)
if (boundRect.Width != 0 && boundRect.Height != 0)
{
var borderGeometryKeypoints =
new BorderGeometryKeypoints(boundRect, borderThickness, cornerRadius, false);

8
src/Avalonia.Dialogs/ManagedFileChooser.cs

@ -10,8 +10,8 @@ using Avalonia.LogicalTree;
namespace Avalonia.Dialogs
{
[TemplatePart("QuickLinks", typeof(Control))]
[TemplatePart("Files", typeof(ListBox))]
[TemplatePart("PART_QuickLinks", typeof(Control))]
[TemplatePart("PART_Files", typeof(ListBox))]
public class ManagedFileChooser : TemplatedControl
{
private Control _quickLinksRoot;
@ -90,8 +90,8 @@ namespace Avalonia.Dialogs
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
_quickLinksRoot = e.NameScope.Get<Control>("QuickLinks");
_filesView = e.NameScope.Get<ListBox>("Files");
_quickLinksRoot = e.NameScope.Get<Control>("PART_QuickLinks");
_filesView = e.NameScope.Get<ListBox>("PART_Files");
}
}
}

4
src/Avalonia.Themes.Fluent/Controls/Calendar.xaml

@ -23,11 +23,11 @@
<Setter Property="Template">
<ControlTemplate>
<StackPanel
Name="Root"
Name="PART_Root"
HorizontalAlignment="Center"
ClipToBounds="True">
<CalendarItem
Name="CalendarItem"
Name="PART_CalendarItem"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"

10
src/Avalonia.Themes.Fluent/Controls/CalendarItem.xaml

@ -79,12 +79,12 @@
-->
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch" RowDefinitions="40,*" MinWidth="294">
<Grid ColumnDefinitions="5*,*,*">
<Button Name="HeaderButton"
<Button Name="PART_HeaderButton"
Theme="{StaticResource FluentCalendarButton}"
Foreground="{TemplateBinding Foreground}"
Padding="12,0,0,0"
HorizontalContentAlignment="Left" />
<Button Name="PreviousButton"
<Button Name="PART_PreviousButton"
Grid.Column="1"
Theme="{StaticResource FluentCalendarButton}"
Foreground="{TemplateBinding Foreground}"
@ -97,7 +97,7 @@
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Button>
<Button Name="NextButton"
<Button Name="PART_NextButton"
Grid.Column="2"
Theme="{StaticResource FluentCalendarButton}"
Foreground="{TemplateBinding Foreground}"
@ -113,7 +113,7 @@
</Grid>
<!--Border below is used only for MonthView but it can't be moved inside of Grid because CalendarItem expects it to be empty and it will cause side-effects-->
<Border Name="BackgroundLayer" Background="{TemplateBinding BorderBrush}" Margin="0,38,0,0" IsVisible="{ReflectionBinding #MonthView.IsVisible}" Grid.Row="1" />
<Grid Name="MonthView" Grid.Row="1" IsVisible="False" MinHeight="290">
<Grid Name="PART_MonthView" Grid.Row="1" IsVisible="False" MinHeight="290">
<Grid.RowDefinitions>
<!--This should always be the week day names??-->
<RowDefinition Height="38" />
@ -134,7 +134,7 @@
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
</Grid>
<Grid Name="YearView"
<Grid Name="PART_YearView"
Background="{TemplateBinding BorderBrush}"
MinHeight="290"
Grid.Row="1"

56
src/Avalonia.Themes.Fluent/Controls/DatePicker.xaml

@ -94,7 +94,7 @@
HorizontalAlignment="Stretch"
VerticalAlignment="Top"/>
<Button Name="FlyoutButton"
<Button Name="PART_FlyoutButton"
Grid.Row="1"
Theme="{StaticResource FluentDatePickerFlyoutButton}"
Foreground="{TemplateBinding Foreground}"
@ -108,28 +108,28 @@
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
TemplatedControl.IsTemplateFocusTarget="True">
<Grid Name="ButtonContentGrid" ColumnDefinitions="78*,Auto,132*,Auto,78*">
<TextBlock Name="DayText" Text="day" HorizontalAlignment="Center"
<Grid Name="PART_ButtonContentGrid" ColumnDefinitions="78*,Auto,132*,Auto,78*">
<TextBlock Name="PART_DayTextBlock" Text="day" HorizontalAlignment="Center"
Padding="{DynamicResource DatePickerHostPadding}"
FontFamily="{TemplateBinding FontFamily}"
FontWeight="{TemplateBinding FontWeight}"
FontSize="{TemplateBinding FontSize}"/>
<TextBlock Name="MonthText" Text="month" TextAlignment="Left"
<TextBlock Name="PART_MonthTextBlock" Text="month" TextAlignment="Left"
Padding="{DynamicResource DatePickerHostMonthPadding}"
FontFamily="{TemplateBinding FontFamily}"
FontWeight="{TemplateBinding FontWeight}"
FontSize="{TemplateBinding FontSize}"/>
<TextBlock Name="YearText" Text="year" HorizontalAlignment="Center"
<TextBlock Name="PART_YearTextBlock" Text="year" HorizontalAlignment="Center"
Padding="{DynamicResource DatePickerHostPadding}"
FontFamily="{TemplateBinding FontFamily}"
FontWeight="{TemplateBinding FontWeight}"
FontSize="{TemplateBinding FontSize}"/>
<Rectangle x:Name="FirstSpacer"
<Rectangle x:Name="PART_FirstSpacer"
Fill="{DynamicResource DatePickerSpacerFill}"
HorizontalAlignment="Center"
Width="1"
Grid.Column="1" />
<Rectangle x:Name="SecondSpacer"
<Rectangle x:Name="PART_SecondSpacer"
Fill="{DynamicResource DatePickerSpacerFill}"
HorizontalAlignment="Center"
Width="1"
@ -137,10 +137,10 @@
</Grid>
</Button>
<Popup Name="Popup" WindowManagerAddShadowHint="False"
<Popup Name="PART_Popup" WindowManagerAddShadowHint="False"
IsLightDismissEnabled="True" PlacementTarget="{TemplateBinding}"
PlacementMode="Bottom">
<DatePickerPresenter Name="PickerPresenter" />
<DatePickerPresenter Name="PART_PickerPresenter" />
</Popup>
</Grid>
@ -181,62 +181,62 @@
Padding="{DynamicResource DateTimeFlyoutBorderPadding}"
MaxHeight="398" CornerRadius="{TemplateBinding CornerRadius}">
<Grid Name="ContentRoot" RowDefinitions="*,Auto">
<Grid Name="PickerContainer">
<Grid Name="PART_PickerContainer">
<Grid.Styles>
<Style Selector="DateTimePickerPanel > ListBoxItem">
<Setter Property="Theme" Value="{StaticResource FluentDateTimePickerItem}" />
</Style>
</Grid.Styles>
<!--Column Definitions set in code, ignore here-->
<Panel Name="MonthHost">
<Panel Name="PART_MonthHost">
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Hidden">
<DateTimePickerPanel Name="MonthSelector"
<DateTimePickerPanel Name="PART_MonthSelector"
PanelType="Month"
ItemHeight="{DynamicResource DatePickerFlyoutPresenterItemHeight}"
ShouldLoop="True" />
</ScrollViewer>
<RepeatButton Name="MonthUpButton" Theme="{StaticResource FluentDateTimePickerUpButton}"/>
<RepeatButton Name="MonthDownButton" Theme="{StaticResource FluentDateTimePickerDownButton}"/>
<RepeatButton Name="PART_MonthUpButton" Theme="{StaticResource FluentDateTimePickerUpButton}"/>
<RepeatButton Name="PART_MonthDownButton" Theme="{StaticResource FluentDateTimePickerDownButton}"/>
</Panel>
<Panel Name="DayHost">
<Panel Name="PART_DayHost">
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Hidden">
<DateTimePickerPanel Name="DaySelector"
<DateTimePickerPanel Name="PART_DaySelector"
PanelType="Day"
ItemHeight="{DynamicResource DatePickerFlyoutPresenterItemHeight}"
ShouldLoop="True" />
</ScrollViewer>
<RepeatButton Name="DayUpButton" Theme="{StaticResource FluentDateTimePickerUpButton}"/>
<RepeatButton Name="DayDownButton" Theme="{StaticResource FluentDateTimePickerDownButton}"/>
<RepeatButton Name="PART_DayUpButton" Theme="{StaticResource FluentDateTimePickerUpButton}"/>
<RepeatButton Name="PART_DayDownButton" Theme="{StaticResource FluentDateTimePickerDownButton}"/>
</Panel>
<Panel Name="YearHost">
<Panel Name="PART_YearHost">
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Hidden">
<DateTimePickerPanel Name="YearSelector"
<DateTimePickerPanel Name="PART_YearSelector"
PanelType="Year"
ItemHeight="{DynamicResource DatePickerFlyoutPresenterItemHeight}"
ShouldLoop="False" />
</ScrollViewer>
<RepeatButton Name="YearUpButton" Theme="{StaticResource FluentDateTimePickerUpButton}"/>
<RepeatButton Name="YearDownButton" Theme="{StaticResource FluentDateTimePickerDownButton}"/>
<RepeatButton Name="PART_YearUpButton" Theme="{StaticResource FluentDateTimePickerUpButton}"/>
<RepeatButton Name="PART_YearDownButton" Theme="{StaticResource FluentDateTimePickerDownButton}"/>
</Panel>
<Rectangle Name="HighlightRect" IsHitTestVisible="False" ZIndex="-1"
Fill="{DynamicResource DatePickerFlyoutPresenterHighlightFill}"
Grid.Column="0" Grid.ColumnSpan="5" VerticalAlignment="Center"
Height="{DynamicResource DatePickerFlyoutPresenterHighlightHeight}" />
<Rectangle Name="FirstSpacer"
<Rectangle Name="PART_FirstSpacer"
Fill="{DynamicResource DatePickerFlyoutPresenterSpacerFill}"
HorizontalAlignment="Center"
Width="{DynamicResource DatePickerSpacerThemeWidth}"
Grid.Column="1" />
<Rectangle Name="SecondSpacer"
<Rectangle Name="PART_SecondSpacer"
Fill="{DynamicResource DatePickerFlyoutPresenterSpacerFill}"
HorizontalAlignment="Center"
Width="{DynamicResource DatePickerSpacerThemeWidth}"
Grid.Column="3" />
</Grid>
<Grid Name="AcceptDismissGrid"
Grid.Row="1"
ColumnDefinitions="*,*">
@ -244,7 +244,7 @@
VerticalAlignment="Top"
Fill="{DynamicResource DatePickerFlyoutPresenterSpacerFill}"
Grid.ColumnSpan="2"/>
<Button Name="AcceptButton"
<Button Name="PART_AcceptButton"
Grid.Column="0"
Theme="{StaticResource FluentDateTimePickerButton}"
Height="{DynamicResource DatePickerFlyoutPresenterAcceptDismissHostGridHeight}"
@ -255,8 +255,8 @@
StrokeThickness="0.75"
Data="M0.5,8.5 5,13.5 15.5,3" />
</Button>
<Button Name="DismissButton"
Grid.Column="1"
<Button Name="PART_DismissButton"
Grid.Column="1"
Theme="{StaticResource FluentDateTimePickerButton}"
Height="{DynamicResource DatePickerFlyoutPresenterAcceptDismissHostGridHeight}"
HorizontalAlignment="Stretch"

4
src/Avalonia.Themes.Fluent/Controls/ManagedFileChooser.xaml

@ -134,7 +134,7 @@
<Setter Property="Template">
<ControlTemplate>
<DockPanel>
<ListBox x:Name="QuickLinks" DockPanel.Dock="Left" Items="{Binding QuickLinks}" SelectedIndex="{Binding QuickLinksSelectedIndex}" Focusable="False">
<ListBox x:Name="PART_QuickLinks" DockPanel.Dock="Left" Items="{Binding QuickLinks}" SelectedIndex="{Binding QuickLinksSelectedIndex}" Focusable="False">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Spacing="4" Orientation="Horizontal" Background="Transparent">
@ -213,7 +213,7 @@
<GridSplitter Grid.Column="7" />
<TextBlock Grid.Column="8" Text="Size" />
</Grid>
<ListBox x:Name="Files"
<ListBox x:Name="PART_Files"
VirtualizationMode="Simple"
Items="{Binding Items}"
Margin="0 5"

60
src/Avalonia.Themes.Fluent/Controls/TimePicker.xaml

@ -94,7 +94,7 @@
HorizontalAlignment="Stretch"
VerticalAlignment="Top" />
<Button x:Name="FlyoutButton"
<Button x:Name="PART_FlyoutButton"
Grid.Row="1"
Theme="{StaticResource FluentTimePickerFlyoutButton}"
Foreground="{TemplateBinding Foreground}"
@ -108,13 +108,13 @@
HorizontalAlignment="Stretch"
VerticalAlignment="Top">
<Grid Name="FlyoutButtonContentGrid">
<Grid Name="PART_FlyoutButtonContentGrid">
<!--Ignore col defs here, set in code-->
<Border x:Name="FirstPickerHost"
<Border x:Name="PART_FirstPickerHost"
Grid.Column="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<TextBlock x:Name="HourTextBlock"
<TextBlock x:Name="PART_HourTextBlock"
HorizontalAlignment="Center"
Padding="{DynamicResource TimePickerHostPadding}"
FontFamily="{TemplateBinding FontFamily}"
@ -122,17 +122,17 @@
FontSize="{TemplateBinding FontSize}" />
</Border>
<Rectangle Name="FirstColumnDivider"
<Rectangle Name="PART_FirstColumnDivider"
Fill="{DynamicResource TimePickerSpacerFill}"
HorizontalAlignment="Center"
Width="{DynamicResource TimePickerSpacerThemeWidth}"
Grid.Column="1" />
<Border x:Name="SecondPickerHost"
<Border x:Name="PART_SecondPickerHost"
Grid.Column="2"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<TextBlock x:Name="MinuteTextBlock"
<TextBlock x:Name="PART_MinuteTextBlock"
HorizontalAlignment="Center"
Padding="{DynamicResource TimePickerHostPadding}"
FontFamily="{TemplateBinding FontFamily}"
@ -140,17 +140,17 @@
FontSize="{TemplateBinding FontSize}"/>
</Border>
<Rectangle Name="SecondColumnDivider"
<Rectangle Name="PART_SecondColumnDivider"
Fill="{DynamicResource TimePickerSpacerFill}"
HorizontalAlignment="Center"
Width="{DynamicResource TimePickerSpacerThemeWidth}"
Grid.Column="3" />
<Border x:Name="ThirdPickerHost"
<Border x:Name="PART_ThirdPickerHost"
Grid.Column="4"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<TextBlock x:Name="PeriodTextBlock"
<TextBlock x:Name="PART_PeriodTextBlock"
HorizontalAlignment="Center"
Padding="{DynamicResource TimePickerHostPadding}"
FontFamily="{TemplateBinding FontFamily}"
@ -160,12 +160,12 @@
</Grid>
</Button>
<Popup Name="Popup"
<Popup Name="PART_Popup"
WindowManagerAddShadowHint="False"
IsLightDismissEnabled="True"
PlacementTarget="{TemplateBinding}"
PlacementMode="Bottom">
<TimePickerPresenter Name="PickerPresenter" />
<TimePickerPresenter Name="PART_PickerPresenter" />
</Popup>
</Grid>
@ -209,42 +209,42 @@
Padding="{DynamicResource DateTimeFlyoutBorderPadding}"
MaxHeight="398">
<Grid Name="ContentPanel" RowDefinitions="*,Auto">
<Grid Name="PickerContainer">
<Grid Name="PART_PickerContainer">
<!--Ignore col defs here, set in code-->
<Panel Name="HourHost" Grid.Column="0">
<Panel Name="PART_HourHost" Grid.Column="0">
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Hidden">
<DateTimePickerPanel Name="HourSelector"
<DateTimePickerPanel Name="PART_HourSelector"
PanelType="Hour"
ShouldLoop="True"
ItemHeight="{DynamicResource TimePickerFlyoutPresenterItemHeight}"/>
</ScrollViewer>
<RepeatButton Name="HourUpButton" Theme="{StaticResource FluentDateTimePickerUpButton}"/>
<RepeatButton Name="HourDownButton" Theme="{StaticResource FluentDateTimePickerDownButton}"/>
<RepeatButton Name="PART_HourUpButton" Theme="{StaticResource FluentDateTimePickerUpButton}"/>
<RepeatButton Name="PART_HourDownButton" Theme="{StaticResource FluentDateTimePickerDownButton}"/>
</Panel>
<Panel Name="MinuteHost" Grid.Column="2">
<Panel Name="PART_MinuteHost" Grid.Column="2">
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Hidden">
<DateTimePickerPanel Name="MinuteSelector"
<DateTimePickerPanel Name="PART_MinuteSelector"
PanelType="Minute"
ShouldLoop="True"
ItemHeight="{DynamicResource TimePickerFlyoutPresenterItemHeight}"/>
</ScrollViewer>
<RepeatButton Name="MinuteUpButton" Theme="{StaticResource FluentDateTimePickerUpButton}"/>
<RepeatButton Name="MinuteDownButton" Theme="{StaticResource FluentDateTimePickerDownButton}"/>
<RepeatButton Name="PART_MinuteUpButton" Theme="{StaticResource FluentDateTimePickerUpButton}"/>
<RepeatButton Name="PART_MinuteDownButton" Theme="{StaticResource FluentDateTimePickerDownButton}"/>
</Panel>
<Panel Name="PeriodHost" Grid.Column="4">
<Panel Name="PART_PeriodHost" Grid.Column="4">
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Hidden">
<DateTimePickerPanel Name="PeriodSelector"
<DateTimePickerPanel Name="PART_PeriodSelector"
PanelType="TimePeriod"
ShouldLoop="False"
ItemHeight="{DynamicResource TimePickerFlyoutPresenterItemHeight}"/>
</ScrollViewer>
<RepeatButton Name="PeriodUpButton" Theme="{StaticResource FluentDateTimePickerUpButton}"/>
<RepeatButton Name="PeriodDownButton" Theme="{StaticResource FluentDateTimePickerDownButton}"/>
<RepeatButton Name="PART_PeriodUpButton" Theme="{StaticResource FluentDateTimePickerUpButton}"/>
<RepeatButton Name="PART_PeriodDownButton" Theme="{StaticResource FluentDateTimePickerDownButton}"/>
</Panel>
<Rectangle x:Name="HighlightRect" ZIndex="-1"
@ -253,12 +253,12 @@
Grid.ColumnSpan="5"
VerticalAlignment="Center"
Height="{DynamicResource TimePickerFlyoutPresenterHighlightHeight}" />
<Rectangle Name="FirstSpacer"
<Rectangle Name="PART_FirstSpacer"
Fill="{DynamicResource TimePickerFlyoutPresenterSpacerFill}"
HorizontalAlignment="Center"
Width="{DynamicResource TimePickerSpacerThemeWidth}"
Grid.Column="1" />
<Rectangle Name="SecondSpacer"
<Rectangle Name="PART_SecondSpacer"
Fill="{DynamicResource TimePickerFlyoutPresenterSpacerFill}"
HorizontalAlignment="Center"
Width="{DynamicResource TimePickerSpacerThemeWidth}"
@ -272,7 +272,7 @@
VerticalAlignment="Top"
Fill="{DynamicResource TimePickerFlyoutPresenterSpacerFill}"
Grid.ColumnSpan="2"/>
<Button Name="AcceptButton"
<Button Name="PART_AcceptButton"
Grid.Column="0"
Theme="{StaticResource FluentDateTimePickerButton}"
Height="{DynamicResource TimePickerFlyoutPresenterAcceptDismissHostGridHeight}"
@ -283,8 +283,8 @@
StrokeThickness="0.75"
Data="M0.5,8.5 5,13.5 15.5,3" />
</Button>
<Button Name="DismissButton"
Grid.Column="1"
<Button Name="PART_DismissButton"
Grid.Column="1"
Theme="{StaticResource FluentDateTimePickerButton}"
Height="{DynamicResource TimePickerFlyoutPresenterAcceptDismissHostGridHeight}"
FontSize="16"

4
src/Avalonia.Themes.Fluent/Controls/ToggleSwitch.xaml

@ -106,13 +106,13 @@
CornerRadius="10" />
<Canvas
x:Name="SwitchKnob"
x:Name="PART_SwitchKnob"
Grid.Row="1"
Width="20"
Height="20"
HorizontalAlignment="Left">
<Grid x:Name="MovingKnobs" Width="20" Height="20">
<Grid x:Name="PART_MovingKnobs" Width="20" Height="20">
<Ellipse
x:Name="SwitchKnobOn"
Fill="{DynamicResource ToggleSwitchKnobFillOn}"

4
src/Avalonia.Themes.Simple/Controls/Calendar.xaml

@ -16,10 +16,10 @@
<Setter Property="HeaderBackground" Value="{DynamicResource ThemeAccentBrush2}" />
<Setter Property="Template">
<ControlTemplate>
<StackPanel Name="Root"
<StackPanel Name="PART_Root"
HorizontalAlignment="Center"
ClipToBounds="True">
<CalendarItem Name="CalendarItem"
<CalendarItem Name="PART_CalendarItem"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"

10
src/Avalonia.Themes.Simple/Controls/CalendarItem.xaml

@ -65,7 +65,7 @@
Fill="{TemplateBinding HeaderBackground}"
Stretch="Fill" />
<Button Name="PreviousButton"
<Button Name="PART_PreviousButton"
HorizontalAlignment="Left"
Classes="CalendarHeader CalendarNavigation"
IsVisible="False">
@ -80,7 +80,7 @@
</Button>
<Button Name="HeaderButton"
<Button Name="PART_HeaderButton"
Grid.Column="1"
Padding="1,5,1,9"
HorizontalAlignment="Center"
@ -89,7 +89,7 @@
FontSize="10.5"
FontWeight="Bold" />
<Button Name="NextButton"
<Button Name="PART_NextButton"
Grid.Column="2"
HorizontalAlignment="Right"
Classes="CalendarHeader CalendarNavigation"
@ -105,7 +105,7 @@
</Button>
<Grid Name="MonthView"
<Grid Name="PART_MonthView"
Grid.Row="1"
Grid.ColumnSpan="3"
Margin="6,-1,6,6"
@ -130,7 +130,7 @@
</Grid.ColumnDefinitions>
</Grid>
<Grid Name="YearView"
<Grid Name="PART_YearView"
Grid.Row="1"
Grid.ColumnSpan="3"
Margin="6,-3,7,6"

52
src/Avalonia.Themes.Simple/Controls/DatePicker.xaml

@ -102,7 +102,7 @@
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}" />
<Button Name="FlyoutButton"
<Button Name="PART_FlyoutButton"
Grid.Row="1"
MinWidth="{DynamicResource DatePickerThemeMinWidth}"
MaxWidth="{DynamicResource DatePickerThemeMaxWidth}"
@ -116,35 +116,35 @@
IsEnabled="{TemplateBinding IsEnabled}"
TemplatedControl.IsTemplateFocusTarget="True"
Theme="{StaticResource SimpleDatePickerFlyoutButton}">
<Grid Name="ButtonContentGrid"
<Grid Name="PART_ButtonContentGrid"
ColumnDefinitions="78*,Auto,132*,Auto,78*">
<TextBlock Name="DayText"
<TextBlock Name="PART_DayTextBlock"
Padding="{DynamicResource DatePickerHostPadding}"
HorizontalAlignment="Center"
FontFamily="{TemplateBinding FontFamily}"
FontSize="{TemplateBinding FontSize}"
FontWeight="{TemplateBinding FontWeight}"
Text="day" />
<TextBlock Name="MonthText"
<TextBlock Name="PART_MonthTextBlock"
Padding="{DynamicResource DatePickerHostMonthPadding}"
FontFamily="{TemplateBinding FontFamily}"
FontSize="{TemplateBinding FontSize}"
FontWeight="{TemplateBinding FontWeight}"
Text="month"
TextAlignment="Left" />
<TextBlock Name="YearText"
<TextBlock Name="PART_YearTextBlock"
Padding="{DynamicResource DatePickerHostPadding}"
HorizontalAlignment="Center"
FontFamily="{TemplateBinding FontFamily}"
FontSize="{TemplateBinding FontSize}"
FontWeight="{TemplateBinding FontWeight}"
Text="year" />
<Rectangle x:Name="FirstSpacer"
<Rectangle x:Name="PART_FirstSpacer"
Grid.Column="1"
Width="1"
HorizontalAlignment="Center"
Fill="{DynamicResource DatePickerSpacerFill}" />
<Rectangle x:Name="SecondSpacer"
<Rectangle x:Name="PART_SecondSpacer"
Grid.Column="3"
Width="1"
HorizontalAlignment="Center"
@ -152,12 +152,12 @@
</Grid>
</Button>
<Popup Name="Popup"
<Popup Name="PART_Popup"
IsLightDismissEnabled="True"
PlacementMode="Bottom"
PlacementTarget="{TemplateBinding}"
WindowManagerAddShadowHint="False">
<DatePickerPresenter Name="PickerPresenter" />
<DatePickerPresenter Name="PART_PickerPresenter" />
</Popup>
</Grid>
@ -197,50 +197,50 @@
CornerRadius="{TemplateBinding CornerRadius}">
<Grid Name="ContentRoot"
RowDefinitions="*,Auto">
<Grid Name="PickerContainer">
<Grid Name="PART_PickerContainer">
<Grid.Styles>
<Style Selector="DateTimePickerPanel > ListBoxItem">
<Setter Property="Theme" Value="{StaticResource SimpleDateTimePickerItem}" />
</Style>
</Grid.Styles>
<!-- Column Definitions set in code, ignore here -->
<Panel Name="MonthHost">
<Panel Name="PART_MonthHost">
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Hidden">
<DateTimePickerPanel Name="MonthSelector"
<DateTimePickerPanel Name="PART_MonthSelector"
ItemHeight="{DynamicResource DatePickerFlyoutPresenterItemHeight}"
PanelType="Month"
ShouldLoop="True" />
</ScrollViewer>
<RepeatButton Name="MonthUpButton"
<RepeatButton Name="PART_MonthUpButton"
Theme="{StaticResource SimpleDateTimePickerUpButton}" />
<RepeatButton Name="MonthDownButton"
<RepeatButton Name="PART_MonthDownButton"
Theme="{StaticResource SimpleDateTimePickerDownButton}" />
</Panel>
<Panel Name="DayHost">
<Panel Name="PART_DayHost">
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Hidden">
<DateTimePickerPanel Name="DaySelector"
<DateTimePickerPanel Name="PART_DaySelector"
ItemHeight="{DynamicResource DatePickerFlyoutPresenterItemHeight}"
PanelType="Day"
ShouldLoop="True" />
</ScrollViewer>
<RepeatButton Name="DayUpButton"
<RepeatButton Name="PART_DayUpButton"
Theme="{StaticResource SimpleDateTimePickerUpButton}" />
<RepeatButton Name="DayDownButton"
<RepeatButton Name="PART_DayDownButton"
Theme="{StaticResource SimpleDateTimePickerDownButton}" />
</Panel>
<Panel Name="YearHost">
<Panel Name="PART_YearHost">
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Hidden">
<DateTimePickerPanel Name="YearSelector"
<DateTimePickerPanel Name="PART_YearSelector"
ItemHeight="{DynamicResource DatePickerFlyoutPresenterItemHeight}"
PanelType="Year"
ShouldLoop="False" />
</ScrollViewer>
<RepeatButton Name="YearUpButton"
<RepeatButton Name="PART_YearUpButton"
Theme="{StaticResource SimpleDateTimePickerUpButton}" />
<RepeatButton Name="YearDownButton"
<RepeatButton Name="PART_YearDownButton"
Theme="{StaticResource SimpleDateTimePickerDownButton}" />
</Panel>
<Rectangle Name="HighlightRect"
@ -255,12 +255,12 @@
Color="{DynamicResource ThemeAccentColor}" />
</Rectangle.Fill>
</Rectangle>
<Rectangle Name="FirstSpacer"
<Rectangle Name="PART_FirstSpacer"
Grid.Column="1"
Width="{DynamicResource DatePickerSpacerThemeWidth}"
HorizontalAlignment="Center"
Fill="{DynamicResource ThemeControlMidHighBrush}" />
<Rectangle Name="SecondSpacer"
<Rectangle Name="PART_SecondSpacer"
Grid.Column="3"
Width="{DynamicResource DatePickerSpacerThemeWidth}"
HorizontalAlignment="Center"
@ -274,7 +274,7 @@
Height="{DynamicResource DatePickerSpacerThemeWidth}"
VerticalAlignment="Top"
Fill="{DynamicResource ThemeControlMidHighBrush}" />
<Button Name="AcceptButton"
<Button Name="PART_AcceptButton"
Grid.Column="0"
Height="{DynamicResource DatePickerFlyoutPresenterAcceptDismissHostGridHeight}"
HorizontalAlignment="Stretch"
@ -285,7 +285,7 @@
StrokeLineCap="Round"
StrokeThickness="0.75" />
</Button>
<Button Name="DismissButton"
<Button Name="PART_DismissButton"
Grid.Column="1"
Height="{DynamicResource DatePickerFlyoutPresenterAcceptDismissHostGridHeight}"
HorizontalAlignment="Stretch"

4
src/Avalonia.Themes.Simple/Controls/ManagedFileChooser.xaml

@ -94,7 +94,7 @@
Text="{Binding FileName}"
Watermark="File name" />
<ListBox x:Name="QuickLinks"
<ListBox x:Name="PART_QuickLinks"
Margin="0,0,5,5"
BorderBrush="Transparent"
DockPanel.Dock="Left"
@ -143,7 +143,7 @@
<TextBlock Grid.Column="8"
Text="Size" />
</Grid>
<ListBox x:Name="Files"
<ListBox x:Name="PART_Files"
Margin="0,5"
Items="{Binding Items}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"

58
src/Avalonia.Themes.Simple/Controls/TimePicker.xaml

@ -102,7 +102,7 @@
ContentTemplate="{TemplateBinding HeaderTemplate}"
Foreground="{DynamicResource ThemeForegroundColor}" />
<Button x:Name="FlyoutButton"
<Button x:Name="PART_FlyoutButton"
Grid.Row="1"
MinWidth="{DynamicResource TimePickerThemeMinWidth}"
MaxWidth="{DynamicResource TimePickerThemeMaxWidth}"
@ -116,13 +116,13 @@
IsEnabled="{TemplateBinding IsEnabled}"
Theme="{StaticResource SimpleTimePickerFlyoutButton}">
<Grid Name="FlyoutButtonContentGrid">
<Grid Name="PART_FlyoutButtonContentGrid">
<!-- Ignore col defs here, set in code -->
<Border x:Name="FirstPickerHost"
<Border x:Name="PART_FirstPickerHost"
Grid.Column="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<TextBlock x:Name="HourTextBlock"
<TextBlock x:Name="PART_HourTextBlock"
Padding="{DynamicResource TimePickerHostPadding}"
HorizontalAlignment="Center"
FontFamily="{TemplateBinding FontFamily}"
@ -130,17 +130,17 @@
FontWeight="{TemplateBinding FontWeight}" />
</Border>
<Rectangle Name="FirstColumnDivider"
<Rectangle Name="PART_FirstColumnDivider"
Grid.Column="1"
Width="{DynamicResource TimePickerSpacerThemeWidth}"
HorizontalAlignment="Center"
Fill="{DynamicResource TimePickerSpacerFill}" />
<Border x:Name="SecondPickerHost"
<Border x:Name="PART_SecondPickerHost"
Grid.Column="2"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<TextBlock x:Name="MinuteTextBlock"
<TextBlock x:Name="PART_MinuteTextBlock"
Padding="{DynamicResource TimePickerHostPadding}"
HorizontalAlignment="Center"
FontFamily="{TemplateBinding FontFamily}"
@ -148,17 +148,17 @@
FontWeight="{TemplateBinding FontWeight}" />
</Border>
<Rectangle Name="SecondColumnDivider"
<Rectangle Name="PART_SecondColumnDivider"
Grid.Column="3"
Width="{DynamicResource TimePickerSpacerThemeWidth}"
HorizontalAlignment="Center"
Fill="{DynamicResource TimePickerSpacerFill}" />
<Border x:Name="ThirdPickerHost"
<Border x:Name="PART_ThirdPickerHost"
Grid.Column="4"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<TextBlock x:Name="PeriodTextBlock"
<TextBlock x:Name="PART_PeriodTextBlock"
Padding="{DynamicResource TimePickerHostPadding}"
HorizontalAlignment="Center"
FontFamily="{TemplateBinding FontFamily}"
@ -168,12 +168,12 @@
</Grid>
</Button>
<Popup Name="Popup"
<Popup Name="PART_Popup"
IsLightDismissEnabled="True"
PlacementMode="Bottom"
PlacementTarget="{TemplateBinding}"
WindowManagerAddShadowHint="False">
<TimePickerPresenter Name="PickerPresenter" />
<TimePickerPresenter Name="PART_PickerPresenter" />
</Popup>
</Grid>
@ -214,50 +214,50 @@
CornerRadius="{TemplateBinding CornerRadius}">
<Grid Name="ContentPanel"
RowDefinitions="*,Auto">
<Grid Name="PickerContainer">
<Grid Name="PART_PickerContainer">
<!-- Ignore col defs here, set in code -->
<Panel Name="HourHost"
<Panel Name="PART_HourHost"
Grid.Column="0">
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Hidden">
<DateTimePickerPanel Name="HourSelector"
<DateTimePickerPanel Name="PART_HourSelector"
ItemHeight="{DynamicResource TimePickerFlyoutPresenterItemHeight}"
PanelType="Hour"
ShouldLoop="True" />
</ScrollViewer>
<RepeatButton Name="HourUpButton"
<RepeatButton Name="PART_HourUpButton"
Theme="{StaticResource SimpleDateTimePickerUpButton}" />
<RepeatButton Name="HourDownButton"
<RepeatButton Name="PART_HourDownButton"
Theme="{StaticResource SimpleDateTimePickerDownButton}" />
</Panel>
<Panel Name="MinuteHost"
<Panel Name="PART_MinuteHost"
Grid.Column="2">
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Hidden">
<DateTimePickerPanel Name="MinuteSelector"
<DateTimePickerPanel Name="PART_MinuteSelector"
ItemHeight="{DynamicResource TimePickerFlyoutPresenterItemHeight}"
PanelType="Minute"
ShouldLoop="True" />
</ScrollViewer>
<RepeatButton Name="MinuteUpButton"
<RepeatButton Name="PART_MinuteUpButton"
Theme="{StaticResource SimpleDateTimePickerUpButton}" />
<RepeatButton Name="MinuteDownButton"
<RepeatButton Name="PART_MinuteDownButton"
Theme="{StaticResource SimpleDateTimePickerDownButton}" />
</Panel>
<Panel Name="PeriodHost"
<Panel Name="PART_PeriodHost"
Grid.Column="4">
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Hidden">
<DateTimePickerPanel Name="PeriodSelector"
<DateTimePickerPanel Name="PART_PeriodSelector"
ItemHeight="{DynamicResource TimePickerFlyoutPresenterItemHeight}"
PanelType="TimePeriod"
ShouldLoop="False" />
</ScrollViewer>
<RepeatButton Name="PeriodUpButton"
<RepeatButton Name="PART_PeriodUpButton"
Theme="{StaticResource SimpleDateTimePickerUpButton}" />
<RepeatButton Name="PeriodDownButton"
<RepeatButton Name="PART_PeriodDownButton"
Theme="{StaticResource SimpleDateTimePickerDownButton}" />
</Panel>
@ -272,12 +272,12 @@
Color="{DynamicResource ThemeAccentColor}" />
</Rectangle.Fill>
</Rectangle>
<Rectangle Name="FirstSpacer"
<Rectangle Name="PART_FirstSpacer"
Grid.Column="1"
Width="{DynamicResource TimePickerSpacerThemeWidth}"
HorizontalAlignment="Center"
Fill="{DynamicResource ThemeControlMidHighBrush}" />
<Rectangle Name="SecondSpacer"
<Rectangle Name="PART_SecondSpacer"
Grid.Column="3"
Width="{DynamicResource TimePickerSpacerThemeWidth}"
HorizontalAlignment="Center"
@ -291,7 +291,7 @@
Height="{DynamicResource TimePickerSpacerThemeWidth}"
VerticalAlignment="Top"
Fill="{DynamicResource ThemeControlMidHighBrush}" />
<Button Name="AcceptButton"
<Button Name="PART_AcceptButton"
Grid.Column="0"
Height="{DynamicResource TimePickerFlyoutPresenterAcceptDismissHostGridHeight}"
HorizontalAlignment="Stretch"
@ -302,7 +302,7 @@
StrokeLineCap="Round"
StrokeThickness="0.75" />
</Button>
<Button Name="DismissButton"
<Button Name="PART_DismissButton"
Grid.Column="1"
Height="{DynamicResource TimePickerFlyoutPresenterAcceptDismissHostGridHeight}"
HorizontalAlignment="Stretch"

4
src/Avalonia.Themes.Simple/Controls/ToggleSwitch.xaml

@ -149,11 +149,11 @@
BorderBrush="{DynamicResource ToggleSwitchStrokeOn}"
BorderThickness="{DynamicResource ToggleSwitchOnStrokeThickness}" />
<Canvas x:Name="SwitchKnob" Grid.Row="1"
<Canvas x:Name="PART_SwitchKnob" Grid.Row="1"
HorizontalAlignment="Left"
Width="20" Height="20">
<Grid x:Name="MovingKnobs"
<Grid x:Name="PART_MovingKnobs"
Width="20" Height="20">
<Grid.Transitions>
<Transitions>

64
src/tools/DevAnalyzers/OnPropertyChangedOverrideAnalyzer.cs

@ -0,0 +1,64 @@
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
namespace DevAnalyzers
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class OnPropertyChangedOverrideAnalyzer : DiagnosticAnalyzer
{
public const string DiagnosticId = "AVADEV2001";
private static readonly DiagnosticDescriptor Rule = new DiagnosticDescriptor(
DiagnosticId,
"Missing invoke base.OnPropertyChanged",
"Method '{0}' do not invoke base.{0}",
"Potential issue",
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
description: "The OnPropertyChanged of the base class was not invoked in the override method declaration, which could lead to unwanted behavior.");
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule);
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();
context.RegisterSymbolAction(AnalyzeMethod, SymbolKind.Method);
}
private static void AnalyzeMethod(SymbolAnalysisContext context)
{
if (context.Symbol is IMethodSymbol currentMethod
&& currentMethod.Name == "OnPropertyChanged"
&& currentMethod.OverriddenMethod is IMethodSymbol originalMethod)
{
var declaration = currentMethod.DeclaringSyntaxReferences.FirstOrDefault()
?.GetSyntax(context.CancellationToken);
if (declaration is not null && context.Compilation.GetSemanticModel(declaration!.SyntaxTree) is { } semanticModel)
{
if (declaration.SyntaxTree.TryGetRoot(out var root))
{
var baseInvocations = root.DescendantNodes().OfType<BaseExpressionSyntax>();
if (baseInvocations.Any())
{
foreach (var baseInvocation in baseInvocations)
{
var parent = baseInvocation.Parent;
var targetSymbol = semanticModel.GetSymbolInfo(parent, context.CancellationToken);
if (SymbolEqualityComparer.Default.Equals(targetSymbol.Symbol, originalMethod))
{
return;
}
}
}
context.ReportDiagnostic(Diagnostic.Create(Rule, currentMethod.Locations[0], currentMethod.Name));
}
}
}
}
}
}

7
src/tools/DevGenerators/CompositionGenerator/CompositionRoslynGenerator.cs

@ -11,8 +11,9 @@ namespace Avalonia.SourceGenerator.CompositionGenerator
{
var schema =
context.AdditionalTextsProvider.Where(static file => file.Path.EndsWith("composition-schema.xml"));
var configs = schema.Select((t, _) =>
(GConfig)new XmlSerializer(typeof(GConfig)).Deserialize(new StringReader(t.GetText().ToString())));
var configs = schema.Select((t, _) => t.GetText())
.Where(source => source is not null)
.Select((source, _) => (GConfig)new XmlSerializer(typeof(GConfig)).Deserialize(new StringReader(source!.ToString())));
context.RegisterSourceOutput(configs, (spc, config) =>
{
var generator = new Generator(new RoslynCompositionGeneratorSink(spc), config);
@ -20,4 +21,4 @@ namespace Avalonia.SourceGenerator.CompositionGenerator
});
}
}
}
}

30
src/tools/DevGenerators/CompositionGenerator/Extensions.cs

@ -7,49 +7,47 @@ namespace Avalonia.SourceGenerator.CompositionGenerator
{
public static class Extensions
{
public static ClassDeclarationSyntax AddModifiers(this ClassDeclarationSyntax cl, params SyntaxKind[] modifiers)
public static ClassDeclarationSyntax AddModifiers(this ClassDeclarationSyntax cl, params SyntaxKind[]? modifiers)
{
if (modifiers == null)
if (modifiers is null)
return cl;
return cl.AddModifiers(modifiers.Select(x => SyntaxFactory.Token(x)).ToArray());
}
public static MethodDeclarationSyntax AddModifiers(this MethodDeclarationSyntax cl, params SyntaxKind[] modifiers)
public static MethodDeclarationSyntax AddModifiers(this MethodDeclarationSyntax cl, params SyntaxKind[]? modifiers)
{
if (modifiers == null)
if (modifiers is null)
return cl;
return cl.AddModifiers(modifiers.Select(x => SyntaxFactory.Token(x)).ToArray());
}
public static PropertyDeclarationSyntax AddModifiers(this PropertyDeclarationSyntax cl, params SyntaxKind[] modifiers)
public static PropertyDeclarationSyntax AddModifiers(this PropertyDeclarationSyntax cl, params SyntaxKind[]? modifiers)
{
if (modifiers == null)
if (modifiers is null)
return cl;
return cl.AddModifiers(modifiers.Select(x => SyntaxFactory.Token(x)).ToArray());
}
public static ConstructorDeclarationSyntax AddModifiers(this ConstructorDeclarationSyntax cl, params SyntaxKind[] modifiers)
public static ConstructorDeclarationSyntax AddModifiers(this ConstructorDeclarationSyntax cl, params SyntaxKind[]? modifiers)
{
if (modifiers == null)
if (modifiers is null)
return cl;
return cl.AddModifiers(modifiers.Select(x => SyntaxFactory.Token(x)).ToArray());
}
public static AccessorDeclarationSyntax AddModifiers(this AccessorDeclarationSyntax cl, params SyntaxKind[] modifiers)
public static AccessorDeclarationSyntax AddModifiers(this AccessorDeclarationSyntax cl, params SyntaxKind[]? modifiers)
{
if (modifiers == null)
if (modifiers is null)
return cl;
return cl.AddModifiers(modifiers.Select(x => SyntaxFactory.Token(x)).ToArray());
}
public static EnumDeclarationSyntax AddModifiers(this EnumDeclarationSyntax cl, params SyntaxKind[] modifiers)
public static EnumDeclarationSyntax AddModifiers(this EnumDeclarationSyntax cl, params SyntaxKind[]? modifiers)
{
if (modifiers == null)
if (modifiers is null)
return cl;
return cl.AddModifiers(modifiers.Select(x => SyntaxFactory.Token(x)).ToArray());
}
public static string WithLowerFirst(this string s)
{
@ -58,7 +56,7 @@ namespace Avalonia.SourceGenerator.CompositionGenerator
return char.ToLowerInvariant(s[0]) + s.Substring(1);
}
public static ExpressionSyntax MemberAccess(params string[] identifiers)
public static ExpressionSyntax MemberAccess(params string[]? identifiers)
{
if (identifiers == null || identifiers.Length == 0)
throw new ArgumentException();
@ -96,4 +94,4 @@ namespace Avalonia.SourceGenerator.CompositionGenerator
? s.Substring(prefix.Length)
: s;
}
}
}

4
src/tools/DevGenerators/CompositionGenerator/Generator.Utils.cs

@ -54,7 +54,7 @@ namespace Avalonia.SourceGenerator.CompositionGenerator
FieldDeclarationSyntax DeclareField(string type, string name, params SyntaxKind[] modifiers) =>
DeclareField(type, name, null, modifiers);
FieldDeclarationSyntax DeclareField(string type, string name, EqualsValueClauseSyntax initializer,
FieldDeclarationSyntax DeclareField(string type, string name, EqualsValueClauseSyntax? initializer,
params SyntaxKind[] modifiers) =>
FieldDeclaration(
VariableDeclaration(ParseTypeName(type),
@ -63,4 +63,4 @@ namespace Avalonia.SourceGenerator.CompositionGenerator
.WithSemicolonToken(Semicolon())
.WithModifiers(TokenList(modifiers.Select(x => Token(x))));
}
}
}

16
src/tools/DevGenerators/CompositionGenerator/Generator.cs

@ -37,8 +37,8 @@ namespace Avalonia.SourceGenerator.CompositionGenerator
string ServerName(string c) => c != null ? ("Server" + c) : "ServerObject";
string ChangesName(string c) => c != null ? (c + "Changes") : "ChangeSet";
string ServerName(string? c) => c != null ? ("Server" + c) : "ServerObject";
string ChangesName(string? c) => c != null ? (c + "Changes") : "ChangeSet";
string ChangedFieldsTypeName(GClass c) => c.Name + "ChangedFields";
string ChangedFieldsFieldName(GClass c) => "_changedFieldsOf" + c.Name;
string PropertyBackingFieldName(GProperty prop) => "_" + prop.Name.WithLowerFirst();
@ -298,10 +298,10 @@ namespace Avalonia.SourceGenerator.CompositionGenerator
if(cl.Implements.Count > 0)
foreach (var impl in cl.Implements)
{
client = client.WithBaseList(client.BaseList.AddTypes(SimpleBaseType(ParseTypeName(impl.Name))));
client = client.WithBaseList(client.BaseList?.AddTypes(SimpleBaseType(ParseTypeName(impl.Name))));
if (impl.ServerName != null)
server = server.WithBaseList(
server.BaseList.AddTypes(SimpleBaseType(ParseTypeName(impl.ServerName))));
server.BaseList?.AddTypes(SimpleBaseType(ParseTypeName(impl.ServerName))));
client = client.AddMembers(
ParseMemberDeclaration($"{impl.ServerName} {impl.Name}.Server => Server;"));
@ -527,7 +527,7 @@ var changed = reader.Read<{ChangedFieldsTypeName(cl)}>();
body = body.AddStatements(
ParseStatement("return base.GetPropertyForAnimation(name);"));
var method = ((MethodDeclarationSyntax) ParseMemberDeclaration(
$"public override Avalonia.Rendering.Composition.Expressions.ExpressionVariant GetPropertyForAnimation(string name){{}}"))
$"public override Avalonia.Rendering.Composition.Expressions.ExpressionVariant GetPropertyForAnimation(string name){{}}")!)
.WithBody(body);
return cl.AddMembers(method);
@ -540,7 +540,7 @@ var changed = reader.Read<{ChangedFieldsTypeName(cl)}>();
body = body.AddStatements(
ParseStatement("return base.GetCompositionProperty(name);"));
var method = ((MethodDeclarationSyntax)ParseMemberDeclaration(
$"public override CompositionProperty? GetCompositionProperty(string name){{}}"))
$"public override CompositionProperty? GetCompositionProperty(string name){{}}")!)
.WithBody(body);
return cl.AddMembers(method);
@ -559,11 +559,11 @@ var changed = reader.Read<{ChangedFieldsTypeName(cl)}>();
);
return cl.AddMembers(
((MethodDeclarationSyntax) ParseMemberDeclaration(
"internal override void StartAnimation(string propertyName, CompositionAnimation animation, Avalonia.Rendering.Composition.Expressions.ExpressionVariant? finalValue){}"))
"internal override void StartAnimation(string propertyName, CompositionAnimation animation, Avalonia.Rendering.Composition.Expressions.ExpressionVariant? finalValue){}")!)
.WithBody(body));
}
}
}
}

1
src/tools/DevGenerators/DevGenerators.csproj

@ -4,6 +4,7 @@
<TargetFramework>netstandard2.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<LangVersion>10</LangVersion>
</PropertyGroup>
<ItemGroup>

11
src/tools/DevGenerators/GetProcAddressInitialization.cs

@ -131,10 +131,13 @@ public class GetProcAddressInitializationGenerator : IIncrementalGenerator
.Append(".GetProcAddress(")
.Append("getProcAddress, ")
.Append(contextName);
var syntaxNode = (AttributeSyntax)attr.ApplicationSyntaxReference.GetSyntax();
foreach (var arg in syntaxNode.ArgumentList.Arguments)
initializeBody.Append(", ").Append(arg.GetText());
if (attr.ApplicationSyntaxReference?.GetSyntax() is AttributeSyntax syntaxNode
&& syntaxNode.ArgumentList is { })
{
foreach (var arg in syntaxNode.ArgumentList.Arguments)
initializeBody.Append(", ").Append(arg.GetText());
}
initializeBody.AppendLine(");");
}
}

57
tests/Avalonia.Controls.UnitTests/BorderTests.cs

@ -78,7 +78,7 @@ namespace Avalonia.Controls.UnitTests
}
};
var root = CreatedRoot(1.5, target);
var root = CreateRoot(1.5, target);
root.LayoutManager.ExecuteInitialLayoutPass();
@ -101,7 +101,7 @@ namespace Avalonia.Controls.UnitTests
}
};
var root = CreatedRoot(1.5, target);
var root = CreateRoot(1.5, target);
root.LayoutManager.ExecuteInitialLayoutPass();
@ -111,7 +111,58 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal(new Size(104, 104), target.DesiredSize);
}
private static TestRoot CreatedRoot(
[Fact]
public void Measure_Arranges_Child_To_Rounded_BorderThickness()
{
Canvas child;
var target = new Border
{
BorderThickness = new Thickness(1),
Width = 82,
Height = 82,
Child = child = new Canvas(),
};
var root = CreateRoot(1.5, target);
root.LayoutManager.ExecuteInitialLayoutPass();
// - 1 pixel border thickness is rounded up to 1.3333; for both sides it is 2.6666
// - Size of 82 needs no rounding
// - Minus border thickness, space for child is 82 - 2.6666 = 79.3333
Assert.Equal(1.3333, child.Bounds.Left, 3);
Assert.Equal(1.3333, child.Bounds.Top, 3);
Assert.Equal(79.3333, child.Bounds.Width, 3);
Assert.Equal(79.3333, child.Bounds.Height, 3);
}
[Fact]
public void Measure_Arranges_Child_With_Rounded_Margin()
{
Border child;
var target = new Border
{
Width = 220,
Height = 220,
Child = child = new Border
{
Margin = new Thickness(0, 25, 25, 25),
},
};
var root = CreateRoot(1.5, target);
root.LayoutManager.ExecuteInitialLayoutPass();
// - 25 margin gets rounded up to 25.3333
// - Size of 220 needs no rounding
Assert.Equal(0, child.Bounds.Left, 3);
Assert.Equal(25.3333, child.Bounds.Top, 3);
Assert.Equal(194.6666, child.Bounds.Width, 3);
Assert.Equal(169.3333, child.Bounds.Height, 3);
}
private static TestRoot CreateRoot(
double scaling,
Control child,
Size? constraint = null)

26
tests/Avalonia.Controls.UnitTests/DatePickerTests.cs

@ -55,7 +55,7 @@ namespace Avalonia.Controls.UnitTests
for(int i = 0; i < container.Children.Count; i++)
{
if(container.Children[i] is TextBlock tb && tb.Name == "DayText")
if(container.Children[i] is TextBlock tb && tb.Name == "PART_DayTextBlock")
{
dayText = tb;
break;
@ -93,7 +93,7 @@ namespace Avalonia.Controls.UnitTests
for (int i = 0; i < container.Children.Count; i++)
{
if (container.Children[i] is TextBlock tb && tb.Name == "MonthText")
if (container.Children[i] is TextBlock tb && tb.Name == "PART_MonthTextBlock")
{
monthText = tb;
break;
@ -131,7 +131,7 @@ namespace Avalonia.Controls.UnitTests
for (int i = 0; i < container.Children.Count; i++)
{
if (container.Children[i] is TextBlock tb && tb.Name == "YearText")
if (container.Children[i] is TextBlock tb && tb.Name == "PART_YearTextBlock")
{
yearText = tb;
break;
@ -171,15 +171,15 @@ namespace Avalonia.Controls.UnitTests
for (int i = 0; i < container.Children.Count; i++)
{
if (container.Children[i] is TextBlock tb && tb.Name == "YearText")
if (container.Children[i] is TextBlock tb && tb.Name == "PART_YearTextBlock")
{
yearText = tb;
}
else if (container.Children[i] is TextBlock tb1 && tb1.Name == "MonthText")
else if (container.Children[i] is TextBlock tb1 && tb1.Name == "PART_MonthTextBlock")
{
monthText = tb1;
}
else if (container.Children[i] is TextBlock tb2 && tb2.Name == "DayText")
else if (container.Children[i] is TextBlock tb2 && tb2.Name == "PART_DayTextBlock")
{
dayText = tb2;
}
@ -218,31 +218,31 @@ namespace Avalonia.Controls.UnitTests
//Skip contentpresenter
var flyoutButton = new Button
{
Name = "FlyoutButton"
Name = "PART_FlyoutButton"
}.RegisterInNameScope(scope);
var contentGrid = new Grid
{
Name = "ButtonContentGrid"
Name = "PART_ButtonContentGrid"
}.RegisterInNameScope(scope);
var dayText = new TextBlock
{
Name = "DayText"
Name = "PART_DayTextBlock"
}.RegisterInNameScope(scope);
var monthText = new TextBlock
{
Name = "MonthText"
Name = "PART_MonthTextBlock"
}.RegisterInNameScope(scope);
var yearText = new TextBlock
{
Name = "YearText"
Name = "PART_YearTextBlock"
}.RegisterInNameScope(scope);
var firstSpacer = new Rectangle
{
Name = "FirstSpacer"
Name = "PART_FirstSpacer"
}.RegisterInNameScope(scope);
var secondSpacer = new Rectangle
{
Name = "SecondSpacer"
Name = "PART_SecondSpacer"
}.RegisterInNameScope(scope);
contentGrid.Children.AddRange(new IControl[] { dayText, monthText, yearText, firstSpacer, secondSpacer });

20
tests/Avalonia.Controls.UnitTests/TimePickerTests.cs

@ -114,52 +114,52 @@ namespace Avalonia.Controls.UnitTests
//Skip contentpresenter
var flyoutButton = new Button
{
Name = "FlyoutButton"
Name = "PART_FlyoutButton"
}.RegisterInNameScope(scope);
var contentGrid = new Grid
{
Name = "FlyoutButtonContentGrid"
Name = "PART_FlyoutButtonContentGrid"
}.RegisterInNameScope(scope);
var firstPickerHost = new Border
{
Name = "FirstPickerHost",
Name = "PART_FirstPickerHost",
Child = new TextBlock
{
Name = "HourTextBlock"
Name = "PART_HourTextBlock"
}.RegisterInNameScope(scope)
}.RegisterInNameScope(scope);
Grid.SetColumn(firstPickerHost, 0);
var secondPickerHost = new Border
{
Name = "SecondPickerHost",
Name = "PART_SecondPickerHost",
Child = new TextBlock
{
Name = "MinuteTextBlock"
Name = "PART_MinuteTextBlock"
}.RegisterInNameScope(scope)
}.RegisterInNameScope(scope);
Grid.SetColumn(secondPickerHost, 2);
var thirdPickerHost = new Border
{
Name = "ThirdPickerHost",
Name = "PART_ThirdPickerHost",
Child = new TextBlock
{
Name = "PeriodTextBlock"
Name = "PART_PeriodTextBlock"
}.RegisterInNameScope(scope)
}.RegisterInNameScope(scope);
Grid.SetColumn(thirdPickerHost, 4);
var firstSpacer = new Rectangle
{
Name = "FirstColumnDivider"
Name = "PART_FirstColumnDivider"
}.RegisterInNameScope(scope);
Grid.SetColumn(firstSpacer, 1);
var secondSpacer = new Rectangle
{
Name = "SecondColumnDivider"
Name = "PART_SecondColumnDivider"
}.RegisterInNameScope(scope);
Grid.SetColumn(secondSpacer, 3);

Loading…
Cancel
Save