diff --git a/.gitignore b/.gitignore
index 971c945246..b5a46e16f4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -198,3 +198,11 @@ info.plist
build-intermediate
obj-Direct2D1/
obj-Skia/
+
+##################
+# Vim
+##################
+.vim
+coc-settings.json
+.ccls-cache
+.ccls
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 3f4fbb0d50..7e3532ee23 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -102,7 +102,7 @@ jobs:
- job: Windows
pool:
- vmImage: 'vs2017-win2016'
+ vmImage: 'windows-2019'
steps:
- task: CmdLine@2
displayName: 'Install Nuke'
diff --git a/build-native.sh b/build-native.sh
old mode 100644
new mode 100755
diff --git a/build/Base.props b/build/Base.props
index e565ab1664..a60373ebb3 100644
--- a/build/Base.props
+++ b/build/Base.props
@@ -2,4 +2,4 @@
-
\ No newline at end of file
+
diff --git a/build/SharedVersion.props b/build/SharedVersion.props
index 4f0b1f0a5b..76abcf6912 100644
--- a/build/SharedVersion.props
+++ b/build/SharedVersion.props
@@ -2,7 +2,7 @@
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
Avalonia
- 0.8.1
+ 0.8.999
Copyright 2019 © The AvaloniaUI Project
https://github.com/AvaloniaUI/Avalonia/blob/master/licence.md
https://github.com/AvaloniaUI/Avalonia/
diff --git a/native/Avalonia.Native/src/OSX/KeyTransform.mm b/native/Avalonia.Native/src/OSX/KeyTransform.mm
index 7486aaad69..971bcf24f8 100644
--- a/native/Avalonia.Native/src/OSX/KeyTransform.mm
+++ b/native/Avalonia.Native/src/OSX/KeyTransform.mm
@@ -26,7 +26,7 @@ const int kVK_ANSI_3 = 0x14;
const int kVK_ANSI_4 = 0x15;
const int kVK_ANSI_6 = 0x16;
const int kVK_ANSI_5 = 0x17;
-//const int kVK_ANSI_Equal = 0x18;
+const int kVK_ANSI_Equal = 0x18;
const int kVK_ANSI_9 = 0x19;
const int kVK_ANSI_7 = 0x1A;
const int kVK_ANSI_Minus = 0x1B;
@@ -45,11 +45,11 @@ const int kVK_ANSI_K = 0x28;
const int kVK_ANSI_Semicolon = 0x29;
const int kVK_ANSI_Backslash = 0x2A;
const int kVK_ANSI_Comma = 0x2B;
-//const int kVK_ANSI_Slash = 0x2C;
+const int kVK_ANSI_Slash = 0x2C;
const int kVK_ANSI_N = 0x2D;
const int kVK_ANSI_M = 0x2E;
const int kVK_ANSI_Period = 0x2F;
-//const int kVK_ANSI_Grave = 0x32;
+const int kVK_ANSI_Grave = 0x32;
const int kVK_ANSI_KeypadDecimal = 0x41;
const int kVK_ANSI_KeypadMultiply = 0x43;
const int kVK_ANSI_KeypadPlus = 0x45;
@@ -57,7 +57,7 @@ const int kVK_ANSI_KeypadClear = 0x47;
const int kVK_ANSI_KeypadDivide = 0x4B;
const int kVK_ANSI_KeypadEnter = 0x4C;
const int kVK_ANSI_KeypadMinus = 0x4E;
-//const int kVK_ANSI_KeypadEquals = 0x51;
+const int kVK_ANSI_KeypadEquals = 0x51;
const int kVK_ANSI_Keypad0 = 0x52;
const int kVK_ANSI_Keypad1 = 0x53;
const int kVK_ANSI_Keypad2 = 0x54;
@@ -121,7 +121,7 @@ const int kVK_UpArrow = 0x7E;
//const int kVK_JIS_Underscore = 0x5E;
//const int kVK_JIS_KeypadComma = 0x5F;
//const int kVK_JIS_Eisu = 0x66;
-//const int kVK_JIS_Kana = 0x68;
+const int kVK_JIS_Kana = 0x68;
std::map s_KeyMap =
{
@@ -148,7 +148,7 @@ const int kVK_UpArrow = 0x7E;
{kVK_ANSI_4, D4},
{kVK_ANSI_6, D6},
{kVK_ANSI_5, D5},
- //{kVK_ANSI_Equal, ?},
+ {kVK_ANSI_Equal, OemPlus},
{kVK_ANSI_9, D9},
{kVK_ANSI_7, D7},
{kVK_ANSI_Minus, OemMinus},
@@ -167,11 +167,11 @@ const int kVK_UpArrow = 0x7E;
{kVK_ANSI_Semicolon, OemSemicolon},
{kVK_ANSI_Backslash, OemBackslash},
{kVK_ANSI_Comma, OemComma},
- //{kVK_ANSI_Slash, ?},
+ {kVK_ANSI_Slash, Oem2},
{kVK_ANSI_N, N},
{kVK_ANSI_M, M},
{kVK_ANSI_Period, OemPeriod},
- //{kVK_ANSI_Grave, ?},
+ {kVK_ANSI_Grave, OemTilde},
{kVK_ANSI_KeypadDecimal, Decimal},
{kVK_ANSI_KeypadMultiply, Multiply},
{kVK_ANSI_KeypadPlus, OemPlus},
@@ -179,7 +179,7 @@ const int kVK_UpArrow = 0x7E;
{kVK_ANSI_KeypadDivide, Divide},
{kVK_ANSI_KeypadEnter, AvnKeyEnter},
{kVK_ANSI_KeypadMinus, OemMinus},
- //{kVK_ANSI_KeypadEquals, ?},
+ {kVK_ANSI_KeypadEquals, OemPlus},
{kVK_ANSI_Keypad0, NumPad0},
{kVK_ANSI_Keypad1, NumPad1},
{kVK_ANSI_Keypad2, NumPad2},
@@ -237,5 +237,6 @@ const int kVK_UpArrow = 0x7E;
{kVK_LeftArrow, Left},
{kVK_RightArrow, Right},
{kVK_DownArrow, Down},
- {kVK_UpArrow, Up}
+ {kVK_UpArrow, Up},
+ {kVK_JIS_Kana, AvnKeyKanaMode},
};
diff --git a/nukebuild/Build.cs b/nukebuild/Build.cs
index a99ac4d026..dd2f27116d 100644
--- a/nukebuild/Build.cs
+++ b/nukebuild/Build.cs
@@ -89,6 +89,29 @@ partial class Build : NukeBuild
}
+ IReadOnlyCollection
diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml
index 4c9b4eaed5..5f24c8062e 100644
--- a/samples/ControlCatalog/MainView.xaml
+++ b/samples/ControlCatalog/MainView.xaml
@@ -37,6 +37,7 @@
+
diff --git a/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml b/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml
index 0ca3567970..f90a0c4658 100644
--- a/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml
+++ b/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml
@@ -37,10 +37,6 @@
-
-
+
+ TabStrip
+ A control which displays a selectable strip of tabs
+
+
+
+ Defined in XAML
+
+ Item 1
+ Item 2
+ Disabled
+
+
+
+
+ Dynamically generated
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/ControlCatalog/Pages/TabStripPage.xaml.cs b/samples/ControlCatalog/Pages/TabStripPage.xaml.cs
new file mode 100644
index 0000000000..f0630cf534
--- /dev/null
+++ b/samples/ControlCatalog/Pages/TabStripPage.xaml.cs
@@ -0,0 +1,45 @@
+using System;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+using Avalonia.Media.Imaging;
+using Avalonia.Platform;
+
+namespace ControlCatalog.Pages
+{
+ public class TabStripPage : UserControl
+ {
+ public TabStripPage()
+ {
+ InitializeComponent();
+
+ DataContext = new[]
+ {
+ new TabStripItemViewModel
+ {
+ Header = "Item 1",
+ },
+ new TabStripItemViewModel
+ {
+ Header = "Item 2",
+ },
+ new TabStripItemViewModel
+ {
+ Header = "Disabled",
+ IsEnabled = false,
+ },
+ };
+ }
+
+ private void InitializeComponent()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+
+ private class TabStripItemViewModel
+ {
+ public string Header { get; set; }
+ public bool IsEnabled { get; set; } = true;
+ }
+ }
+}
diff --git a/samples/ControlCatalog/SideBar.xaml b/samples/ControlCatalog/SideBar.xaml
index 3047b1e519..3513e94107 100644
--- a/samples/ControlCatalog/SideBar.xaml
+++ b/samples/ControlCatalog/SideBar.xaml
@@ -29,8 +29,7 @@
Name="PART_ItemsPresenter"
Items="{TemplateBinding Items}"
ItemsPanel="{TemplateBinding ItemsPanel}"
- ItemTemplate="{TemplateBinding ItemTemplate}"
- MemberSelector="{TemplateBinding MemberSelector}">
+ ItemTemplate="{TemplateBinding ItemTemplate}">
+ ItemTemplate="{TemplateBinding ItemTemplate}">
-
\ No newline at end of file
+
diff --git a/src/Android/Avalonia.Android/Avalonia.Android.csproj b/src/Android/Avalonia.Android/Avalonia.Android.csproj
index 9c3d4fb3a1..0089ea3b8d 100644
--- a/src/Android/Avalonia.Android/Avalonia.Android.csproj
+++ b/src/Android/Avalonia.Android/Avalonia.Android.csproj
@@ -1,6 +1,6 @@
- monoandroid44
+ monoandroid80
true
diff --git a/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj b/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj
index c2c0cd4301..1b2b205d45 100644
--- a/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj
+++ b/src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj
@@ -16,7 +16,7 @@
Resources\Resource.Designer.cs
Off
False
- v4.4
+ v8.0
Properties\AndroidManifest.xml
@@ -150,6 +150,7 @@
+
diff --git a/src/Avalonia.Base/Data/Converters/DefaultValueConverter.cs b/src/Avalonia.Base/Data/Converters/DefaultValueConverter.cs
index 990a4b04f2..0ffd6a9539 100644
--- a/src/Avalonia.Base/Data/Converters/DefaultValueConverter.cs
+++ b/src/Avalonia.Base/Data/Converters/DefaultValueConverter.cs
@@ -31,7 +31,7 @@ namespace Avalonia.Data.Converters
{
if (value == null)
{
- return AvaloniaProperty.UnsetValue;
+ return targetType.IsValueType ? AvaloniaProperty.UnsetValue : null;
}
if (typeof(ICommand).IsAssignableFrom(targetType) && value is Delegate d && d.Method.GetParameters().Length <= 1)
diff --git a/src/Avalonia.Base/Utilities/SynchronousCompletionAsyncResult.cs b/src/Avalonia.Base/Utilities/SynchronousCompletionAsyncResult.cs
new file mode 100644
index 0000000000..f321b2b2f1
--- /dev/null
+++ b/src/Avalonia.Base/Utilities/SynchronousCompletionAsyncResult.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+
+namespace Avalonia.Utilities
+{
+ ///
+ /// A task-like operation that is guaranteed to finish continuations synchronously,
+ /// can be used for parametrized one-shot events
+ ///
+ public struct SynchronousCompletionAsyncResult : INotifyCompletion
+ {
+ private readonly SynchronousCompletionAsyncResultSource _source;
+ private readonly T _result;
+ private readonly bool _isValid;
+ internal SynchronousCompletionAsyncResult(SynchronousCompletionAsyncResultSource source)
+ {
+ _source = source;
+ _result = default;
+ _isValid = true;
+ }
+
+ public SynchronousCompletionAsyncResult(T result)
+ {
+ _result = result;
+ _source = null;
+ _isValid = true;
+ }
+
+ static void ThrowNotInitialized() =>
+ throw new InvalidOperationException("This SynchronousCompletionAsyncResult was not initialized");
+
+ public bool IsCompleted
+ {
+ get
+ {
+ if (!_isValid)
+ ThrowNotInitialized();
+ return _source == null || _source.IsCompleted;
+ }
+ }
+
+ public T GetResult()
+ {
+ if (!_isValid)
+ ThrowNotInitialized();
+ return _source == null ? _result : _source.Result;
+ }
+
+
+ public void OnCompleted(Action continuation)
+ {
+ if (!_isValid)
+ ThrowNotInitialized();
+ if (_source == null)
+ continuation();
+ else
+ _source.OnCompleted(continuation);
+ }
+
+ public SynchronousCompletionAsyncResult GetAwaiter() => this;
+ }
+
+ ///
+ /// Source for incomplete SynchronousCompletionAsyncResult
+ ///
+ ///
+ public class SynchronousCompletionAsyncResultSource
+ {
+ private T _result;
+ internal bool IsCompleted { get; private set; }
+ public SynchronousCompletionAsyncResult AsyncResult => new SynchronousCompletionAsyncResult(this);
+
+ internal T Result => IsCompleted ?
+ _result :
+ throw new InvalidOperationException("Asynchronous operation is not yet completed");
+
+ private List _continuations;
+
+ internal void OnCompleted(Action continuation)
+ {
+ if(_continuations==null)
+ _continuations = new List();
+ _continuations.Add(continuation);
+ }
+
+ public void SetResult(T result)
+ {
+ if (IsCompleted)
+ throw new InvalidOperationException("Asynchronous operation is already completed");
+ _result = result;
+ IsCompleted = true;
+ if(_continuations!=null)
+ foreach (var c in _continuations)
+ c();
+ _continuations = null;
+ }
+
+ public void TrySetResult(T result)
+ {
+ if(IsCompleted)
+ return;
+ SetResult(result);
+ }
+ }
+}
diff --git a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
index c54d8e19a1..0dd52c9b48 100644
--- a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
+++ b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
@@ -75,9 +75,9 @@ namespace Avalonia.Build.Tasks
.First(c => c.Parameters.Count == 1));
var runtimeHelpers = typeSystem.GetType("Avalonia.Markup.Xaml.XamlIl.Runtime.XamlIlRuntimeHelpers");
- var rootServiceProviderField = asm.MainModule.ImportReference(
- typeSystem.GetTypeReference(runtimeHelpers).Resolve().Fields
- .First(x => x.Name == "RootServiceProviderV1"));
+ var createRootServiceProviderMethod = asm.MainModule.ImportReference(
+ typeSystem.GetTypeReference(runtimeHelpers).Resolve().Methods
+ .First(x => x.Name == "CreateRootServiceProviderV2"));
var loaderDispatcherDef = new TypeDefinition("CompiledAvaloniaXaml", "!XamlLoader",
TypeAttributes.Class, asm.MainModule.TypeSystem.Object);
@@ -211,7 +211,7 @@ namespace Avalonia.Build.Tasks
trampoline.Parameters.Add(new ParameterDefinition(classTypeDefinition));
classTypeDefinition.Methods.Add(trampoline);
- var regularStart = Instruction.Create(OpCodes.Ldsfld, rootServiceProviderField);
+ var regularStart = Instruction.Create(OpCodes.Call, createRootServiceProviderMethod);
trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldsfld, designLoaderField));
trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Brfalse, regularStart));
@@ -307,7 +307,7 @@ namespace Avalonia.Build.Tasks
i.Add(Instruction.Create(OpCodes.Newobj, parameterlessConstructor));
else
{
- i.Add(Instruction.Create(OpCodes.Ldsfld, rootServiceProviderField));
+ i.Add(Instruction.Create(OpCodes.Call, createRootServiceProviderMethod));
i.Add(Instruction.Create(OpCodes.Call, compiledBuildMethod));
}
diff --git a/src/Avalonia.Controls.DataGrid/Themes/Default.xaml b/src/Avalonia.Controls.DataGrid/Themes/Default.xaml
index 2889a5c77c..eaa267ba66 100644
--- a/src/Avalonia.Controls.DataGrid/Themes/Default.xaml
+++ b/src/Avalonia.Controls.DataGrid/Themes/Default.xaml
@@ -195,7 +195,6 @@
-
@@ -230,4 +229,4 @@
-
\ No newline at end of file
+
diff --git a/src/Avalonia.Controls/AutoCompleteBox.cs b/src/Avalonia.Controls/AutoCompleteBox.cs
index b87e10d284..1e2fc9f9d0 100644
--- a/src/Avalonia.Controls/AutoCompleteBox.cs
+++ b/src/Avalonia.Controls/AutoCompleteBox.cs
@@ -345,7 +345,6 @@ namespace Avalonia.Controls
///
private IDisposable _collectionChangeSubscription;
- private IMemberSelector _valueMemberSelector;
private Func>> _asyncPopulator;
private CancellationTokenSource _populationCancellationTokenSource;
@@ -541,12 +540,6 @@ namespace Avalonia.Controls
o => o.Items,
(o, v) => o.Items = v);
- public static readonly DirectProperty ValueMemberSelectorProperty =
- AvaloniaProperty.RegisterDirect(
- nameof(ValueMemberSelector),
- o => o.ValueMemberSelector,
- (o, v) => o.ValueMemberSelector = v);
-
public static readonly DirectProperty>>> AsyncPopulatorProperty =
AvaloniaProperty.RegisterDirect>>>(
nameof(AsyncPopulator),
@@ -795,7 +788,7 @@ namespace Avalonia.Controls
var template =
new FuncDataTemplate(
typeof(object),
- o =>
+ (o, _) =>
{
var control = new ContentControl();
control.Bind(ContentControl.ContentProperty, value);
@@ -958,20 +951,6 @@ namespace Avalonia.Controls
}
}
- ///
- /// Gets or sets the MemberSelector that is used to get values for
- /// display in the text portion of the
- /// control.
- ///
- /// The MemberSelector that is used to get values for display in
- /// the text portion of the
- /// control.
- public IMemberSelector ValueMemberSelector
- {
- get { return _valueMemberSelector; }
- set { SetAndRaise(ValueMemberSelectorProperty, ref _valueMemberSelector, value); }
- }
-
///
/// Gets or sets the selected item in the drop-down.
///
@@ -1841,11 +1820,6 @@ namespace Avalonia.Controls
return _valueBindingEvaluator.GetDynamicValue(value) ?? String.Empty;
}
- if (_valueMemberSelector != null)
- {
- value = _valueMemberSelector.Select(value);
- }
-
return value == null ? String.Empty : value.ToString();
}
diff --git a/src/Avalonia.Controls/ComboBox.cs b/src/Avalonia.Controls/ComboBox.cs
index 5d427df5a6..f32b8fabc6 100644
--- a/src/Avalonia.Controls/ComboBox.cs
+++ b/src/Avalonia.Controls/ComboBox.cs
@@ -333,8 +333,7 @@ namespace Avalonia.Controls
}
else
{
- var selector = MemberSelector;
- SelectionBoxItem = selector != null ? selector.Select(item) : item;
+ SelectionBoxItem = item;
}
}
diff --git a/src/Avalonia.Controls/ContextMenu.cs b/src/Avalonia.Controls/ContextMenu.cs
index cf5fa512e8..d0804107b3 100644
--- a/src/Avalonia.Controls/ContextMenu.cs
+++ b/src/Avalonia.Controls/ContextMenu.cs
@@ -1,12 +1,12 @@
using System;
using System.ComponentModel;
using System.Linq;
-using System.Reactive.Linq;
using Avalonia.Controls.Generators;
using Avalonia.Controls.Platform;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Input;
+using Avalonia.Interactivity;
using Avalonia.Layout;
using Avalonia.LogicalTree;
@@ -91,9 +91,14 @@ namespace Avalonia.Controls
/// The control.
public void Open(Control control)
{
+ if (IsOpen)
+ {
+ return;
+ }
+
if (_popup == null)
{
- _popup = new Popup()
+ _popup = new Popup
{
PlacementMode = PlacementMode.Pointer,
PlacementTarget = control,
@@ -108,7 +113,14 @@ namespace Avalonia.Controls
((ISetLogicalParent)_popup).SetParent(control);
_popup.Child = this;
_popup.IsOpen = true;
+
IsOpen = true;
+
+ RaiseEvent(new RoutedEventArgs
+ {
+ RoutedEvent = MenuOpenedEvent,
+ Source = this,
+ });
}
///
@@ -116,13 +128,15 @@ namespace Avalonia.Controls
///
public override void Close()
{
+ if (!IsOpen)
+ {
+ return;
+ }
+
if (_popup != null && _popup.IsVisible)
{
_popup.IsOpen = false;
}
-
- SelectedIndex = -1;
- IsOpen = false;
}
protected override IItemContainerGenerator CreateItemContainerGenerator()
@@ -130,6 +144,18 @@ namespace Avalonia.Controls
return new MenuItemContainerGenerator(this);
}
+ private void CloseCore()
+ {
+ SelectedIndex = -1;
+ IsOpen = false;
+
+ RaiseEvent(new RoutedEventArgs
+ {
+ RoutedEvent = MenuClosedEvent,
+ Source = this,
+ });
+ }
+
private void PopupOpened(object sender, EventArgs e)
{
Focus();
@@ -146,8 +172,7 @@ namespace Avalonia.Controls
i.IsSubMenuOpen = false;
}
- contextMenu.IsOpen = false;
- contextMenu.SelectedIndex = -1;
+ contextMenu.CloseCore();
}
}
diff --git a/src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs b/src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs
index 83d1c4aae3..2d48a7d33b 100644
--- a/src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs
+++ b/src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs
@@ -8,7 +8,7 @@ using JetBrains.Annotations;
namespace Avalonia.Controls.Embedding
{
- public class EmbeddableControlRoot : TopLevel, IStyleable, IFocusScope, INameScope, IDisposable
+ public class EmbeddableControlRoot : TopLevel, IStyleable, IFocusScope, IDisposable
{
public EmbeddableControlRoot(IEmbeddableWindowImpl impl) : base(impl)
{
@@ -51,25 +51,6 @@ namespace Avalonia.Controls.Embedding
return rv;
}
- private readonly NameScope _nameScope = new NameScope();
- public event EventHandler Registered
- {
- add { _nameScope.Registered += value; }
- remove { _nameScope.Registered -= value; }
- }
-
- public event EventHandler Unregistered
- {
- add { _nameScope.Unregistered += value; }
- remove { _nameScope.Unregistered -= value; }
- }
-
- public void Register(string name, object element) => _nameScope.Register(name, element);
-
- public object Find(string name) => _nameScope.Find(name);
-
- public void Unregister(string name) => _nameScope.Unregister(name);
-
Type IStyleable.StyleKey => typeof(EmbeddableControlRoot);
public void Dispose() => PlatformImpl?.Dispose();
}
diff --git a/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevel.cs b/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevel.cs
index c4f83ffd54..d326ab5734 100644
--- a/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevel.cs
+++ b/src/Avalonia.Controls/Embedding/Offscreen/OffscreenTopLevel.cs
@@ -30,25 +30,6 @@ namespace Avalonia.Controls.Embedding.Offscreen
init.EndInit();
}
}
-
- private readonly NameScope _nameScope = new NameScope();
- public event EventHandler Registered
- {
- add { _nameScope.Registered += value; }
- remove { _nameScope.Registered -= value; }
- }
-
- public event EventHandler Unregistered
- {
- add { _nameScope.Unregistered += value; }
- remove { _nameScope.Unregistered -= value; }
- }
-
- public void Register(string name, object element) => _nameScope.Register(name, element);
-
- public object Find(string name) => _nameScope.Find(name);
-
- public void Unregister(string name) => _nameScope.Unregister(name);
Type IStyleable.StyleKey => typeof(EmbeddableControlRoot);
public void Dispose()
diff --git a/src/Avalonia.Controls/Generators/IItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/IItemContainerGenerator.cs
index 653a4f5dcb..2d6757219d 100644
--- a/src/Avalonia.Controls/Generators/IItemContainerGenerator.cs
+++ b/src/Avalonia.Controls/Generators/IItemContainerGenerator.cs
@@ -49,12 +49,8 @@ namespace Avalonia.Controls.Generators
/// The index of the item of data in the control's items.
///
/// The item.
- /// An optional member selector.
/// The created controls.
- ItemContainerInfo Materialize(
- int index,
- object item,
- IMemberSelector selector);
+ ItemContainerInfo Materialize(int index, object item);
///
/// Removes a set of created containers.
@@ -84,11 +80,7 @@ namespace Avalonia.Controls.Generators
/// The removed containers.
IEnumerable RemoveRange(int startingIndex, int count);
- bool TryRecycle(
- int oldIndex,
- int newIndex,
- object item,
- IMemberSelector selector);
+ bool TryRecycle(int oldIndex, int newIndex, object item);
///
/// Clears all created containers and returns the removed controls.
diff --git a/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs
index f1a1f94a01..4fd6f4135c 100644
--- a/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs
+++ b/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs
@@ -54,13 +54,9 @@ namespace Avalonia.Controls.Generators
public virtual Type ContainerType => null;
///
- public ItemContainerInfo Materialize(
- int index,
- object item,
- IMemberSelector selector)
+ public ItemContainerInfo Materialize(int index, object item)
{
- var i = selector != null ? selector.Select(item) : item;
- var container = new ItemContainerInfo(CreateContainer(i), item, index);
+ var container = new ItemContainerInfo(CreateContainer(item), item, index);
_containers.Add(container.Index, container);
Materialized?.Invoke(this, new ItemContainerEventArgs(container));
@@ -138,14 +134,7 @@ namespace Avalonia.Controls.Generators
}
///
- public virtual bool TryRecycle(
- int oldIndex,
- int newIndex,
- object item,
- IMemberSelector selector)
- {
- return false;
- }
+ public virtual bool TryRecycle(int oldIndex, int newIndex, object item) => false;
///
public virtual IEnumerable Clear()
diff --git a/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs b/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs
index 320d6c8faf..d1d1c2b172 100644
--- a/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs
+++ b/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs
@@ -79,11 +79,7 @@ namespace Avalonia.Controls.Generators
}
///
- public override bool TryRecycle(
- int oldIndex,
- int newIndex,
- object item,
- IMemberSelector selector)
+ public override bool TryRecycle(int oldIndex, int newIndex, object item)
{
var container = ContainerFromIndex(oldIndex);
@@ -92,16 +88,14 @@ namespace Avalonia.Controls.Generators
throw new IndexOutOfRangeException("Could not recycle container: not materialized.");
}
- var i = selector != null ? selector.Select(item) : item;
-
- container.SetValue(ContentProperty, i);
+ container.SetValue(ContentProperty, item);
if (!(item is IControl))
{
- container.DataContext = i;
+ container.DataContext = item;
}
- var info = MoveContainer(oldIndex, newIndex, i);
+ var info = MoveContainer(oldIndex, newIndex, item);
RaiseRecycled(new ItemContainerEventArgs(info));
return true;
diff --git a/src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs
index 304c86dbf7..c06a64443c 100644
--- a/src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs
+++ b/src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs
@@ -92,7 +92,6 @@ namespace Avalonia.Controls.Generators
result.DataContext = item;
}
- NameScope.SetNameScope((Control)(object)result, new NameScope());
Index.Add(item, result);
return result;
@@ -118,16 +117,22 @@ namespace Avalonia.Controls.Generators
return base.RemoveRange(startingIndex, count);
}
- public override bool TryRecycle(int oldIndex, int newIndex, object item, IMemberSelector selector)
+ public override bool TryRecycle(int oldIndex, int newIndex, object item) => false;
+
+ class WrapperTreeDataTemplate : ITreeDataTemplate
{
- return false;
+ private readonly IDataTemplate _inner;
+ public WrapperTreeDataTemplate(IDataTemplate inner) => _inner = inner;
+ public IControl Build(object param) => _inner.Build(param);
+ public bool SupportsRecycling => _inner.SupportsRecycling;
+ public bool Match(object data) => _inner.Match(data);
+ public InstancedBinding ItemsSelector(object item) => null;
}
private ITreeDataTemplate GetTreeDataTemplate(object item, IDataTemplate primary)
{
var template = Owner.FindDataTemplate(item, primary) ?? FuncDataTemplate.Default;
- var treeTemplate = template as ITreeDataTemplate ??
- new FuncTreeDataTemplate(typeof(object), template.Build, x => null);
+ var treeTemplate = template as ITreeDataTemplate ?? new WrapperTreeDataTemplate(template);
return treeTemplate;
}
}
diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs
index a292ff7d0a..902e55bde6 100644
--- a/src/Avalonia.Controls/ItemsControl.cs
+++ b/src/Avalonia.Controls/ItemsControl.cs
@@ -54,12 +54,6 @@ namespace Avalonia.Controls
public static readonly StyledProperty ItemTemplateProperty =
AvaloniaProperty.Register(nameof(ItemTemplate));
- ///
- /// Defines the property.
- ///
- public static readonly StyledProperty MemberSelectorProperty =
- AvaloniaProperty.Register(nameof(MemberSelector));
-
private IEnumerable _items = new AvaloniaList
public static readonly RoutedEvent MenuOpenedEvent =
- RoutedEvent.Register
protected void SelectAll()
{
- if ((SelectionMode & (SelectionMode.Multiple | SelectionMode.Toggle)) == 0)
- {
- throw new NotSupportedException("Multiple selection is not enabled on this control.");
- }
-
UpdateSelectedItems(() =>
{
_selection.Clear();
@@ -523,7 +534,14 @@ namespace Avalonia.Controls.Primitives
var toggle = (toggleModifier || (mode & SelectionMode.Toggle) != 0);
var range = multi && rangeModifier;
- if (range)
+ if (rightButton)
+ {
+ if (!_selection.Contains(index))
+ {
+ UpdateSelectedItem(index);
+ }
+ }
+ else if (range)
{
UpdateSelectedItems(() =>
{
@@ -582,7 +600,7 @@ namespace Avalonia.Controls.Primitives
}
else
{
- UpdateSelectedItem(index, !(rightButton && _selection.Contains(index)));
+ UpdateSelectedItem(index);
}
if (Presenter?.Panel != null)
diff --git a/src/Avalonia.Controls/Primitives/TabStrip.cs b/src/Avalonia.Controls/Primitives/TabStrip.cs
index 346d4340fb..ec0dbd124c 100644
--- a/src/Avalonia.Controls/Primitives/TabStrip.cs
+++ b/src/Avalonia.Controls/Primitives/TabStrip.cs
@@ -13,11 +13,8 @@ namespace Avalonia.Controls.Primitives
private static readonly FuncTemplate DefaultPanel =
new FuncTemplate(() => new WrapPanel { Orientation = Orientation.Horizontal });
- private static IMemberSelector s_MemberSelector = new FuncMemberSelector