diff --git a/samples/ControlCatalog.Android/ControlCatalog.Android.csproj b/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
index 272632e7eb..d8f0f39977 100644
--- a/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
+++ b/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
@@ -32,7 +32,7 @@
True
False
False
- armeabi;armeabi-v7a;x86
+ armeabi-v7a;x86
Xamarin
False
False
@@ -51,7 +51,7 @@
True
False
False
- armeabi,armeabi-v7a,x86
+ armeabi-v7a,x86
Xamarin
False
False
diff --git a/samples/ControlCatalog/SideBar.xaml b/samples/ControlCatalog/SideBar.xaml
index fea55bcb07..0eae348717 100644
--- a/samples/ControlCatalog/SideBar.xaml
+++ b/samples/ControlCatalog/SideBar.xaml
@@ -63,13 +63,13 @@
-
-
diff --git a/samples/interop/WindowsInteropTest/Program.cs b/samples/interop/WindowsInteropTest/Program.cs
index fac06d74b0..9f005b942d 100644
--- a/samples/interop/WindowsInteropTest/Program.cs
+++ b/samples/interop/WindowsInteropTest/Program.cs
@@ -15,7 +15,7 @@ namespace WindowsInteropTest
{
System.Windows.Forms.Application.EnableVisualStyles();
System.Windows.Forms.Application.SetCompatibleTextRenderingDefault(false);
- AppBuilder.Configure().UseWin32().UseDirect2D1().SetupWithoutStarting();
+ AppBuilder.Configure().UseWin32().UseDirect2D1().UseDataGrid().SetupWithoutStarting();
System.Windows.Forms.Application.Run(new SelectorForm());
}
}
diff --git a/samples/interop/WindowsInteropTest/WindowsInteropTest.csproj b/samples/interop/WindowsInteropTest/WindowsInteropTest.csproj
index 33c7b85f06..c067d38595 100644
--- a/samples/interop/WindowsInteropTest/WindowsInteropTest.csproj
+++ b/samples/interop/WindowsInteropTest/WindowsInteropTest.csproj
@@ -104,6 +104,10 @@
{b09b78d8-9b26-48b0-9149-d64a2f120f3f}
Avalonia.Base
+
+ {3278f3a9-9509-4a3f-a15b-bdc8b5bff632}
+ Avalonia.Controls.DataGrid
+
{d2221c82-4a25-4583-9b43-d791e3f6820c}
Avalonia.Controls
@@ -185,6 +189,5 @@
-
\ No newline at end of file
diff --git a/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj b/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj
index b493fd1ef2..c2c0cd4301 100644
--- a/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj
+++ b/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj
@@ -32,7 +32,7 @@
True
False
False
- armeabi;armeabi-v7a;x86
+ armeabi-v7a;x86
Xamarin
False
True
@@ -52,7 +52,7 @@
True
False
False
- armeabi,armeabi-v7a,x86
+ armeabi-v7a,x86
Xamarin
False
False
diff --git a/src/Avalonia.Base/Data/BindingOperations.cs b/src/Avalonia.Base/Data/BindingOperations.cs
index ca148659e6..15de6c4d0d 100644
--- a/src/Avalonia.Base/Data/BindingOperations.cs
+++ b/src/Avalonia.Base/Data/BindingOperations.cs
@@ -65,7 +65,11 @@ namespace Avalonia.Data
return Disposable.Empty;
}
case BindingMode.OneWayToSource:
- return target.GetObservable(property).Subscribe(binding.Subject);
+ return Observable.CombineLatest(
+ binding.Observable,
+ target.GetObservable(property),
+ (_, v) => v)
+ .Subscribe(x => binding.Subject.OnNext(x));
default:
throw new ArgumentException("Invalid binding mode.");
}
diff --git a/src/Avalonia.Base/Data/Core/PropertyAccessorNode.cs b/src/Avalonia.Base/Data/Core/PropertyAccessorNode.cs
index a916142675..df8f46a7d7 100644
--- a/src/Avalonia.Base/Data/Core/PropertyAccessorNode.cs
+++ b/src/Avalonia.Base/Data/Core/PropertyAccessorNode.cs
@@ -59,8 +59,8 @@ namespace Avalonia.Data.Core
$"Could not find a matching property accessor for {PropertyName}.");
}
- accessor.Subscribe(ValueChanged);
_accessor = accessor;
+ accessor.Subscribe(ValueChanged);
}
protected override void StopListeningCore()
diff --git a/src/Avalonia.Controls/Control.cs b/src/Avalonia.Controls/Control.cs
index a7ee027e70..ca5edae4a9 100644
--- a/src/Avalonia.Controls/Control.cs
+++ b/src/Avalonia.Controls/Control.cs
@@ -1,6 +1,7 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
+using System;
using System.ComponentModel;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
@@ -20,7 +21,7 @@ namespace Avalonia.Controls
///
/// - A property to allow user-defined data to be attached to the control.
///
- public class Control : InputElement, IControl, INamed, ISupportInitialize, IVisualBrushInitialize, IRequiresTemplateInSetter
+ public class Control : InputElement, IControl, INamed, ISupportInitialize, IVisualBrushInitialize, ISetterValue
{
///
/// Defines the property.
@@ -90,6 +91,13 @@ namespace Avalonia.Controls
///
bool IDataTemplateHost.IsDataTemplatesInitialized => _dataTemplates != null;
+ ///
+ void ISetterValue.Initialize(ISetter setter)
+ {
+ throw new InvalidOperationException(
+ "Cannot use a control as a Setter value. Wrap the control in a .");
+ }
+
///
void IVisualBrushInitialize.EnsureInitialized()
{
diff --git a/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs b/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs
index 942104d61b..73854b9f60 100644
--- a/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs
+++ b/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs
@@ -336,7 +336,18 @@ namespace Avalonia.Controls.Platform
if (e.MouseButton == MouseButton.Left && item?.HasSubMenu == true)
{
- Open(item, false);
+ if (item.IsSubMenuOpen)
+ {
+ if (item.IsTopLevel)
+ {
+ CloseMenu(item);
+ }
+ }
+ else
+ {
+ Open(item, false);
+ }
+
e.Handled = true;
}
}
diff --git a/src/Avalonia.Controls/Presenters/CarouselPresenter.cs b/src/Avalonia.Controls/Presenters/CarouselPresenter.cs
index ba2c7c91d8..a3123cf8c6 100644
--- a/src/Avalonia.Controls/Presenters/CarouselPresenter.cs
+++ b/src/Avalonia.Controls/Presenters/CarouselPresenter.cs
@@ -38,7 +38,6 @@ namespace Avalonia.Controls.Presenters
Carousel.PageTransitionProperty.AddOwner();
private int _selectedIndex = -1;
- // private Task _current;
private Task _currentTransition;
private int _queuedTransitionIndex = -1;
@@ -47,6 +46,7 @@ namespace Avalonia.Controls.Presenters
///
static CarouselPresenter()
{
+ IsVirtualizedProperty.Changed.AddClassHandler(x => x.IsVirtualizedChanged);
SelectedIndexProperty.Changed.AddClassHandler(x => x.SelectedIndexChanged);
}
@@ -94,58 +94,67 @@ namespace Avalonia.Controls.Presenters
set { SetValue(PageTransitionProperty, value); }
}
- ///
- protected override void PanelCreated(IPanel panel)
- {
-#pragma warning disable 4014
- MoveToPage(-1, SelectedIndex);
-#pragma warning restore 4014
- }
-
///
protected override void ItemsChanged(NotifyCollectionChangedEventArgs e)
{
- switch (e.Action)
+ if (!IsVirtualized)
{
- case NotifyCollectionChangedAction.Remove:
- if (!IsVirtualized)
- {
- var generator = ItemContainerGenerator;
- var containers = generator.RemoveRange(e.OldStartingIndex, e.OldItems.Count);
- Panel.Children.RemoveAll(containers.Select(x => x.ContainerControl));
+ base.ItemsChanged(e);
-#pragma warning disable 4014
- MoveToPage(-1, SelectedIndex);
-#pragma warning restore 4014
- }
- break;
-
- case NotifyCollectionChangedAction.Reset:
- {
- var generator = ItemContainerGenerator;
- var containers = generator.Containers.ToList();
- generator.Clear();
- Panel.Children.RemoveAll(containers.Select(x => x.ContainerControl));
-
-#pragma warning disable 4014
- var newIndex = SelectedIndex;
+ if (Items == null || SelectedIndex >= Items.Count())
+ {
+ SelectedIndex = Items.Count() - 1;
+ }
- if(SelectedIndex < 0)
+ foreach (var c in ItemContainerGenerator.Containers)
+ {
+ c.ContainerControl.IsVisible = c.Index == SelectedIndex;
+ }
+ }
+ else if (SelectedIndex != -1 && Panel != null)
+ {
+ switch (e.Action)
+ {
+ case NotifyCollectionChangedAction.Add:
+ if (e.NewStartingIndex > SelectedIndex)
{
- if(Items != null && Items.Count() > 0)
- {
- newIndex = 0;
- }
- else
- {
- newIndex = -1;
- }
+ return;
}
-
- MoveToPage(-1, newIndex);
-#pragma warning restore 4014
- }
- break;
+ break;
+ case NotifyCollectionChangedAction.Remove:
+ if (e.OldStartingIndex > SelectedIndex)
+ {
+ return;
+ }
+ break;
+ case NotifyCollectionChangedAction.Replace:
+ if (e.OldStartingIndex > SelectedIndex ||
+ e.OldStartingIndex + e.OldItems.Count - 1 < SelectedIndex)
+ {
+ return;
+ }
+ break;
+ case NotifyCollectionChangedAction.Move:
+ if (e.OldStartingIndex > SelectedIndex &&
+ e.NewStartingIndex > SelectedIndex)
+ {
+ return;
+ }
+ break;
+ }
+
+ if (Items == null || SelectedIndex >= Items.Count())
+ {
+ SelectedIndex = Items.Count() - 1;
+ }
+
+ Panel.Children.Clear();
+ ItemContainerGenerator.Clear();
+
+ if (SelectedIndex != -1)
+ {
+ GetOrCreateContainer(SelectedIndex);
+ }
}
}
@@ -201,7 +210,7 @@ namespace Avalonia.Controls.Presenters
{
var container = ItemContainerGenerator.ContainerFromIndex(index);
- if (container == null)
+ if (container == null && IsVirtualized)
{
var item = Items.Cast