diff --git a/build/XUnit.props b/build/XUnit.props
index 53f524b8e9..a75e1bac86 100644
--- a/build/XUnit.props
+++ b/build/XUnit.props
@@ -13,6 +13,6 @@
$(MSBuildThisFileDirectory)\avalonia.snk
- True
+ False
diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml
index 488aa0535f..f001425964 100644
--- a/samples/ControlCatalog/MainView.xaml
+++ b/samples/ControlCatalog/MainView.xaml
@@ -14,7 +14,6 @@
-
@@ -45,6 +44,7 @@
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
+
diff --git a/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml b/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml
index a49616e543..1a53217842 100644
--- a/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml
+++ b/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml
@@ -1,5 +1,6 @@
AutoCompleteBox
@@ -56,6 +57,16 @@
Width="200"
Margin="0,0,0,8"
FilterMode="None"/>
+
+
+
+
+
+
+
diff --git a/samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml b/samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml
index c3f9f65dd9..4ac2330403 100644
--- a/samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml
+++ b/samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml
@@ -1,6 +1,7 @@
+ x:Class="ControlCatalog.Pages.ButtonSpinnerPage"
+ xmlns:sys="clr-namespace:System;assembly=netstandard">
ButtonSpinner
@@ -19,6 +20,14 @@
ShowButtonSpinner="{Binding #showSpinCheck.IsChecked}">
+
+
+
+
+
+
diff --git a/samples/ControlCatalog/Pages/ComboBoxPage.xaml b/samples/ControlCatalog/Pages/ComboBoxPage.xaml
index 369f703718..025b85492c 100644
--- a/samples/ControlCatalog/Pages/ComboBoxPage.xaml
+++ b/samples/ControlCatalog/Pages/ComboBoxPage.xaml
@@ -1,6 +1,7 @@
+ x:Class="ControlCatalog.Pages.ComboBoxPage"
+ xmlns:sys="clr-namespace:System;assembly=netstandard">
ComboBox
A drop-down list.
@@ -35,6 +36,16 @@
+
+
+ Inline Items
+ Inline Item 2
+ Inline Item 3
+ Inline Item 4
+
+
+
+
diff --git a/samples/ControlCatalog/Pages/DateTimePickerPage.xaml b/samples/ControlCatalog/Pages/DateTimePickerPage.xaml
index af6b6e8605..45056a9a76 100644
--- a/samples/ControlCatalog/Pages/DateTimePickerPage.xaml
+++ b/samples/ControlCatalog/Pages/DateTimePickerPage.xaml
@@ -2,6 +2,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:sys="clr-namespace:System;assembly=netstandard"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="ControlCatalog.Pages.DateTimePickerPage">
@@ -30,6 +31,16 @@
+
+
+
+
+
+
+
+
+
A DatePicker with day formatted and year hidden.
+
+
+
+
+
+
+
+
A TimePicker with a header and minute increments specified.
diff --git a/samples/ControlCatalog/Pages/LabelsPage.axaml b/samples/ControlCatalog/Pages/LabelsPage.axaml
index 32c46f080d..961e7ba7e6 100644
--- a/samples/ControlCatalog/Pages/LabelsPage.axaml
+++ b/samples/ControlCatalog/Pages/LabelsPage.axaml
@@ -25,11 +25,11 @@
-
+
-
+
-
+
diff --git a/samples/ControlCatalog/Pages/NumericUpDownPage.xaml b/samples/ControlCatalog/Pages/NumericUpDownPage.xaml
index 0d7e5da17f..d75622f1fb 100644
--- a/samples/ControlCatalog/Pages/NumericUpDownPage.xaml
+++ b/samples/ControlCatalog/Pages/NumericUpDownPage.xaml
@@ -1,5 +1,6 @@
Numeric up-down control
@@ -75,6 +76,15 @@
+
+ NumericUpDown with Validation Errors:
+
+
+
+
+
diff --git a/samples/ControlCatalog/Pages/RelativePanelPage.axaml b/samples/ControlCatalog/Pages/RelativePanelPage.axaml
index 3657d52bd9..4dcdcc195f 100644
--- a/samples/ControlCatalog/Pages/RelativePanelPage.axaml
+++ b/samples/ControlCatalog/Pages/RelativePanelPage.axaml
@@ -23,16 +23,16 @@
-
+
-
+
-
+
@@ -41,19 +41,19 @@
-
+
-
+
-
+
-
+
-
+
diff --git a/samples/ControlCatalog/Pages/SliderPage.xaml b/samples/ControlCatalog/Pages/SliderPage.xaml
index ea31ed0050..b3f32ed421 100644
--- a/samples/ControlCatalog/Pages/SliderPage.xaml
+++ b/samples/ControlCatalog/Pages/SliderPage.xaml
@@ -1,5 +1,6 @@
Slider
@@ -21,6 +22,15 @@
IsSnapToTickEnabled="True"
Ticks="0,20,25,40,75,100"
Width="300" />
+
+
+
+
+
+ x:Class="ControlCatalog.Pages.TextBoxPage"
+ xmlns:sys="clr-namespace:System;assembly=netstandard">
@@ -11,12 +12,18 @@
Spacing="16">
-
+
+
+
+
+
+
+
/// Label focus Target
///
+ [ResolveByName]
public IInputElement Target
{
get => _target;
diff --git a/src/Avalonia.Controls/Primitives/Popup.cs b/src/Avalonia.Controls/Primitives/Popup.cs
index becb489557..b445de0472 100644
--- a/src/Avalonia.Controls/Primitives/Popup.cs
+++ b/src/Avalonia.Controls/Primitives/Popup.cs
@@ -265,6 +265,7 @@ namespace Avalonia.Controls.Primitives
///
/// Gets or sets the control that is used to determine the popup's position.
///
+ [ResolveByName]
public Control? PlacementTarget
{
get { return GetValue(PlacementTargetProperty); }
diff --git a/src/Avalonia.Controls/RelativePanel.AttachedProperties.cs b/src/Avalonia.Controls/RelativePanel.AttachedProperties.cs
index f64c26682b..562b104b04 100644
--- a/src/Avalonia.Controls/RelativePanel.AttachedProperties.cs
+++ b/src/Avalonia.Controls/RelativePanel.AttachedProperties.cs
@@ -55,6 +55,7 @@ namespace Avalonia.Controls
///
/// The object to which the property value is written.
/// The value to set. (The element to position this element above.)
+ [ResolveByName]
public static void SetAbove(AvaloniaObject obj, object value)
{
obj.SetValue(AboveProperty, value);
@@ -121,6 +122,7 @@ namespace Avalonia.Controls
///
/// The object to which the property value is written.
/// The value to set. (The element to align this element's bottom edge with.)
+ [ResolveByName]
public static void SetAlignBottomWith(AvaloniaObject obj, object value)
{
obj.SetValue(AlignBottomWithProperty, value);
@@ -185,6 +187,7 @@ namespace Avalonia.Controls
///
/// The object to which the property value is written.
/// The value to set. (The element to align this element's horizontal center with.)
+ [ResolveByName]
public static void SetAlignHorizontalCenterWith(AvaloniaObject obj, object value)
{
obj.SetValue(AlignHorizontalCenterWithProperty, value);
@@ -250,6 +253,7 @@ namespace Avalonia.Controls
///
/// The object to which the property value is written.
/// The value to set. (The element to align this element's left edge with.)
+ [ResolveByName]
public static void SetAlignLeftWith(AvaloniaObject obj, object value)
{
obj.SetValue(AlignLeftWithProperty, value);
@@ -315,6 +319,7 @@ namespace Avalonia.Controls
///
/// The object to which the property value is written.
/// The value to set. (The element to align this element's right edge with.)
+ [ResolveByName]
public static void SetAlignRightWith(AvaloniaObject obj, object value)
{
obj.SetValue(AlignRightWithProperty, value);
@@ -376,6 +381,7 @@ namespace Avalonia.Controls
///
/// The object to which the property value is written.
/// The value to set. (The element to align this element's top edge with.)
+ [ResolveByName]
public static void SetAlignTopWith(AvaloniaObject obj, object value)
{
obj.SetValue(AlignTopWithProperty, value);
@@ -437,7 +443,7 @@ namespace Avalonia.Controls
///
/// The object to which the property value is written.
/// The value to set. (The element to align this element's horizontal center with.)
-
+ [ResolveByName]
public static void SetAlignVerticalCenterWith(AvaloniaObject obj, object value)
{
obj.SetValue(AlignVerticalCenterWithProperty, value);
@@ -468,7 +474,7 @@ namespace Avalonia.Controls
///
/// The object to which the property value is written.
/// The value to set. (The element to position this element below.)
-
+ [ResolveByName]
public static void SetBelow(AvaloniaObject obj, object value)
{
obj.SetValue(BelowProperty, value);
@@ -500,6 +506,7 @@ namespace Avalonia.Controls
///
/// The object to which the property value is written.
/// The value to set. (The element to position this element to the left of.)
+ [ResolveByName]
public static void SetLeftOf(AvaloniaObject obj, object value)
{
obj.SetValue(LeftOfProperty, value);
@@ -531,6 +538,7 @@ namespace Avalonia.Controls
///
/// The object to which the property value is written.
/// The value to set. (The element to position this element to the right of.)
+ [ResolveByName]
public static void SetRightOf(AvaloniaObject obj, object value)
{
obj.SetValue(RightOfProperty, value);
diff --git a/src/Avalonia.Controls/ResolveByNameAttribute.cs b/src/Avalonia.Controls/ResolveByNameAttribute.cs
index a00e3f8a1b..a13b10d630 100644
--- a/src/Avalonia.Controls/ResolveByNameAttribute.cs
+++ b/src/Avalonia.Controls/ResolveByNameAttribute.cs
@@ -2,8 +2,12 @@
namespace Avalonia.Controls
{
+ ///
+ /// Indicates that the property resolves an element by Name or x:Name.
+ /// When applying this to attached properties, ensure to put on both
+ /// the Getter and Setter methods.
+ ///
public class ResolveByNameAttribute : Attribute
{
-
}
}
diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/TreeNode.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/TreeNode.cs
index d9a0d17518..9363c28705 100644
--- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/TreeNode.cs
+++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/TreeNode.cs
@@ -23,6 +23,8 @@ namespace Avalonia.Diagnostics.ViewModels
if (visual is IControl control)
{
+ ElementName = control.Name;
+
var removed = Observable.FromEventPattern(
x => control.DetachedFromLogicalTree += x,
x => control.DetachedFromLogicalTree -= x);
@@ -61,6 +63,11 @@ namespace Avalonia.Diagnostics.ViewModels
private set { RaiseAndSetIfChanged(ref _classes, value); }
}
+ public string ElementName
+ {
+ get;
+ }
+
public IVisual Visual
{
get;
diff --git a/src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml b/src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml
index b2d3a8bddb..8aad5fffd8 100644
--- a/src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml
+++ b/src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml
@@ -26,6 +26,12 @@
+
+
+
+
diff --git a/src/Avalonia.Diagnostics/Diagnostics/Views/MainWindow.xaml.cs b/src/Avalonia.Diagnostics/Diagnostics/Views/MainWindow.xaml.cs
index 10861538ae..c4f9185728 100644
--- a/src/Avalonia.Diagnostics/Diagnostics/Views/MainWindow.xaml.cs
+++ b/src/Avalonia.Diagnostics/Diagnostics/Views/MainWindow.xaml.cs
@@ -76,7 +76,13 @@ namespace Avalonia.Diagnostics.Views
if (e.Modifiers == modifiers)
{
var point = (Root as IInputRoot)?.MouseDevice?.GetPosition(Root) ?? default;
- var control = Root.GetVisualsAt(point, x => (!(x is AdornerLayer) && x.IsVisible))
+
+ var control = Root.GetVisualsAt(point, x =>
+ {
+ if (x is AdornerLayer || !x.IsVisible) return false;
+ if (!(x is IInputElement ie)) return true;
+ return ie.IsHitTestVisible;
+ })
.FirstOrDefault();
if (control != null)
diff --git a/src/Avalonia.Diagnostics/Diagnostics/Views/TreePageView.xaml b/src/Avalonia.Diagnostics/Diagnostics/Views/TreePageView.xaml
index a1e6ca7d37..98de9b611e 100644
--- a/src/Avalonia.Diagnostics/Diagnostics/Views/TreePageView.xaml
+++ b/src/Avalonia.Diagnostics/Diagnostics/Views/TreePageView.xaml
@@ -2,7 +2,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:Avalonia.Diagnostics.ViewModels"
x:Class="Avalonia.Diagnostics.Views.TreePageView">
-
+
+
diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs
index bc0916c8da..2cf1fe2963 100644
--- a/src/Avalonia.Native/WindowImplBase.cs
+++ b/src/Avalonia.Native/WindowImplBase.cs
@@ -341,8 +341,7 @@ namespace Avalonia.Native
public void Invalidate(Rect rect)
{
- if (!_deferredRendering && _native != null)
- _native.Invalidate(new AvnRect { Height = rect.Height, Width = rect.Width, X = rect.X, Y = rect.Y });
+ _native?.Invalidate(new AvnRect { Height = rect.Height, Width = rect.Width, X = rect.X, Y = rect.Y });
}
public void SetInputRoot(IInputRoot inputRoot)
diff --git a/src/Avalonia.ReactiveUI/ReactiveUserControl.cs b/src/Avalonia.ReactiveUI/ReactiveUserControl.cs
index fc48a8853d..31f4691c90 100644
--- a/src/Avalonia.ReactiveUI/ReactiveUserControl.cs
+++ b/src/Avalonia.ReactiveUI/ReactiveUserControl.cs
@@ -1,3 +1,6 @@
+using System;
+using System.Reactive.Disposables;
+using System.Reactive.Linq;
using Avalonia;
using Avalonia.VisualTree;
using Avalonia.Controls;
@@ -6,8 +9,10 @@ using ReactiveUI;
namespace Avalonia.ReactiveUI
{
///
- /// A ReactiveUI UserControl that implements
- /// and will activate your ViewModel automatically if it supports activation.
+ /// A ReactiveUI that implements the interface and
+ /// will activate your ViewModel automatically if the view model implements .
+ /// When the DataContext property changes, this class will update the ViewModel property with the new DataContext
+ /// value, and vice versa.
///
/// ViewModel type.
public class ReactiveUserControl : UserControl, IViewFor where TViewModel : class
@@ -20,7 +25,14 @@ namespace Avalonia.ReactiveUI
///
public ReactiveUserControl()
{
- DataContextChanged += (sender, args) => ViewModel = DataContext as TViewModel;
+ // This WhenActivated block calls ViewModel's WhenActivated
+ // block if the ViewModel implements IActivatableViewModel.
+ this.WhenActivated(disposables => { });
+
+ this.ObservableForProperty(x => x.ViewModel, false, true)
+ .Subscribe(args => DataContext = args.Value);
+ this.ObservableForProperty(x => x.DataContext, false, true)
+ .Subscribe(args => ViewModel = args.Value as TViewModel);
}
///
diff --git a/src/Avalonia.ReactiveUI/ReactiveWindow.cs b/src/Avalonia.ReactiveUI/ReactiveWindow.cs
index 5695a727af..1204266b63 100644
--- a/src/Avalonia.ReactiveUI/ReactiveWindow.cs
+++ b/src/Avalonia.ReactiveUI/ReactiveWindow.cs
@@ -1,3 +1,6 @@
+using System;
+using System.Reactive.Disposables;
+using System.Reactive.Linq;
using Avalonia;
using Avalonia.VisualTree;
using Avalonia.Controls;
@@ -6,8 +9,10 @@ using ReactiveUI;
namespace Avalonia.ReactiveUI
{
///
- /// A ReactiveUI Window that implements
- /// and will activate your ViewModel automatically if it supports activation.
+ /// A ReactiveUI that implements the interface and will
+ /// activate your ViewModel automatically if the view model implements . When
+ /// the DataContext property changes, this class will update the ViewModel property with the new DataContext value,
+ /// and vice versa.
///
/// ViewModel type.
public class ReactiveWindow : Window, IViewFor where TViewModel : class
@@ -20,7 +25,14 @@ namespace Avalonia.ReactiveUI
///
public ReactiveWindow()
{
- DataContextChanged += (sender, args) => ViewModel = DataContext as TViewModel;
+ // This WhenActivated block calls ViewModel's WhenActivated
+ // block if the ViewModel implements IActivatableViewModel.
+ this.WhenActivated(disposables => { });
+
+ this.ObservableForProperty(x => x.ViewModel, false, true)
+ .Subscribe(args => DataContext = args.Value);
+ this.ObservableForProperty(x => x.DataContext, false, true)
+ .Subscribe(args => ViewModel = args.Value as TViewModel);
}
///
diff --git a/src/Avalonia.Themes.Fluent/ButtonSpinner.xaml b/src/Avalonia.Themes.Fluent/ButtonSpinner.xaml
index 82265ea282..12b4845522 100644
--- a/src/Avalonia.Themes.Fluent/ButtonSpinner.xaml
+++ b/src/Avalonia.Themes.Fluent/ButtonSpinner.xaml
@@ -65,56 +65,59 @@
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/ComboBox.xaml b/src/Avalonia.Themes.Fluent/ComboBox.xaml
index 8155264f18..2eee656dc6 100644
--- a/src/Avalonia.Themes.Fluent/ComboBox.xaml
+++ b/src/Avalonia.Themes.Fluent/ComboBox.xaml
@@ -44,105 +44,107 @@
-
-
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ Grid.Column="1"
+ IsHitTestVisible="False"
+ Margin="0,0,10,0"
+ Height="12"
+ Width="12"
+ HorizontalAlignment="Right"
+ VerticalAlignment="Center">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -232,4 +234,9 @@
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/DataValidationErrors.xaml b/src/Avalonia.Themes.Fluent/DataValidationErrors.xaml
index 902fc74c0c..ed31f7b573 100644
--- a/src/Avalonia.Themes.Fluent/DataValidationErrors.xaml
+++ b/src/Avalonia.Themes.Fluent/DataValidationErrors.xaml
@@ -14,39 +14,31 @@
-
-
+
+
-
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/DatePicker.xaml b/src/Avalonia.Themes.Fluent/DatePicker.xaml
index 6fbfa1bbf7..b6e36861e0 100644
--- a/src/Avalonia.Themes.Fluent/DatePicker.xaml
+++ b/src/Avalonia.Themes.Fluent/DatePicker.xaml
@@ -125,77 +125,79 @@
-
-
+
+
+
-
+
-
-
-
+
+
+
-
+
+
@@ -228,6 +230,11 @@
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
@@ -102,56 +104,58 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
@@ -260,4 +264,12 @@
+
+
+
+
diff --git a/src/Avalonia.Themes.Fluent/TextBox.xaml b/src/Avalonia.Themes.Fluent/TextBox.xaml
index 162835ae10..139a61abdf 100644
--- a/src/Avalonia.Themes.Fluent/TextBox.xaml
+++ b/src/Avalonia.Themes.Fluent/TextBox.xaml
@@ -36,16 +36,7 @@
-
-
-
-
-
+
-
-
-
+
-
-
+
diff --git a/src/Avalonia.Themes.Fluent/TimePicker.xaml b/src/Avalonia.Themes.Fluent/TimePicker.xaml
index 84352213e1..91969d8733 100644
--- a/src/Avalonia.Themes.Fluent/TimePicker.xaml
+++ b/src/Avalonia.Themes.Fluent/TimePicker.xaml
@@ -41,94 +41,96 @@
-
-
+
+
+
-
+
-
-
-
+
+
+
-
+
+
@@ -161,6 +163,10 @@
+
+