committed by
GitHub
255 changed files with 4538 additions and 1984 deletions
@ -0,0 +1,5 @@ |
|||
<ProjectConfiguration> |
|||
<Settings> |
|||
<IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely> |
|||
</Settings> |
|||
</ProjectConfiguration> |
|||
@ -1,7 +1,7 @@ |
|||
<Project> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0-preview.2" PrivateAssets="All" /> |
|||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
|
|||
@ -1,6 +1,6 @@ |
|||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<ItemGroup> |
|||
<PackageReference Include="SkiaSharp" Version="2.80.2-preview.33" /> |
|||
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="SkiaSharp.NativeAssets.Linux" Version="2.80.2-preview.33" /> |
|||
<PackageReference Include="SkiaSharp" Version="2.80.2" /> |
|||
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="SkiaSharp.NativeAssets.Linux" Version="2.80.2" /> |
|||
</ItemGroup> |
|||
</Project> |
|||
|
|||
@ -1,35 +1,25 @@ |
|||
<UserControl xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
x:Class="ControlCatalog.Pages.ListBoxPage"> |
|||
<StackPanel Orientation="Vertical" Spacing="4"> |
|||
<TextBlock Classes="h1">ListBox</TextBlock> |
|||
<TextBlock Classes="h2">Hosts a collection of ListBoxItem.</TextBlock> |
|||
|
|||
<StackPanel Orientation="Horizontal" |
|||
Margin="0,16,0,0" |
|||
HorizontalAlignment="Center" |
|||
Spacing="16"> |
|||
<StackPanel Orientation="Vertical" Spacing="8"> |
|||
<ListBox Items="{Binding Items}" |
|||
Selection="{Binding Selection}" |
|||
AutoScrollToSelectedItem="True" |
|||
SelectionMode="{Binding SelectionMode}" |
|||
Width="250" |
|||
Height="350"/> |
|||
|
|||
<Button Command="{Binding AddItemCommand}">Add</Button> |
|||
|
|||
<Button Command="{Binding RemoveItemCommand}">Remove</Button> |
|||
|
|||
<Button Command="{Binding SelectRandomItemCommand}">Select Random Item</Button> |
|||
|
|||
<ComboBox SelectedIndex="{Binding SelectionMode, Mode=TwoWay}"> |
|||
<ComboBoxItem>Single</ComboBoxItem> |
|||
<ComboBoxItem>Multiple</ComboBoxItem> |
|||
<ComboBoxItem>Toggle</ComboBoxItem> |
|||
<ComboBoxItem>AlwaysSelected</ComboBoxItem> |
|||
</ComboBox> |
|||
</StackPanel> |
|||
<DockPanel> |
|||
<StackPanel DockPanel.Dock="Top" Margin="4"> |
|||
<TextBlock Classes="h1">ListBox</TextBlock> |
|||
<TextBlock Classes="h2">Hosts a collection of ListBoxItem.</TextBlock> |
|||
</StackPanel> |
|||
</StackPanel> |
|||
<StackPanel DockPanel.Dock="Right" Margin="4"> |
|||
<CheckBox IsChecked="{Binding Multiple}">Multiple</CheckBox> |
|||
<CheckBox IsChecked="{Binding Toggle}">Toggle</CheckBox> |
|||
<CheckBox IsChecked="{Binding AlwaysSelected}">AlwaysSelected</CheckBox> |
|||
<CheckBox IsChecked="{Binding AutoScrollToSelectedItem}">AutoScrollToSelectedItem</CheckBox> |
|||
</StackPanel> |
|||
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal" Margin="4"> |
|||
<Button Command="{Binding AddItemCommand}">Add</Button> |
|||
<Button Command="{Binding RemoveItemCommand}">Remove</Button> |
|||
<Button Command="{Binding SelectRandomItemCommand}">Select Random Item</Button> |
|||
</StackPanel> |
|||
<ListBox Items="{Binding Items}" |
|||
Selection="{Binding Selection}" |
|||
AutoScrollToSelectedItem="{Binding AutoScrollToSelectedItem}" |
|||
SelectionMode="{Binding SelectionMode}"/> |
|||
</DockPanel> |
|||
</UserControl> |
|||
|
|||
@ -0,0 +1,8 @@ |
|||
<Application |
|||
xmlns="https://github.com/avaloniaui" |
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
|||
x:Class="Sandbox.App"> |
|||
<Application.Styles> |
|||
<StyleInclude Source="avares://Avalonia.Themes.Fluent/Accents/FluentDark.xaml"/> |
|||
</Application.Styles> |
|||
</Application> |
|||
@ -0,0 +1,22 @@ |
|||
using Avalonia; |
|||
using Avalonia.Controls.ApplicationLifetimes; |
|||
using Avalonia.Markup.Xaml; |
|||
|
|||
namespace Sandbox |
|||
{ |
|||
public class App : Application |
|||
{ |
|||
public override void Initialize() |
|||
{ |
|||
AvaloniaXamlLoader.Load(this); |
|||
} |
|||
|
|||
public override void OnFrameworkInitializationCompleted() |
|||
{ |
|||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktopLifetime) |
|||
{ |
|||
desktopLifetime.MainWindow = new MainWindow(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,4 @@ |
|||
<Window xmlns="https://github.com/avaloniaui" |
|||
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' |
|||
x:Class="Sandbox.MainWindow"> |
|||
</Window> |
|||
@ -0,0 +1,20 @@ |
|||
using Avalonia; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Markup.Xaml; |
|||
|
|||
namespace Sandbox |
|||
{ |
|||
public class MainWindow : Window |
|||
{ |
|||
public MainWindow() |
|||
{ |
|||
this.InitializeComponent(); |
|||
this.AttachDevTools(); |
|||
} |
|||
|
|||
private void InitializeComponent() |
|||
{ |
|||
AvaloniaXamlLoader.Load(this); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
using Avalonia; |
|||
using Avalonia.ReactiveUI; |
|||
|
|||
namespace Sandbox |
|||
{ |
|||
public class Program |
|||
{ |
|||
static void Main(string[] args) |
|||
{ |
|||
AppBuilder.Configure<App>() |
|||
.UsePlatformDetect() |
|||
.UseReactiveUI() |
|||
.LogToDebug() |
|||
.StartWithClassicDesktopLifetime(args); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<OutputType>WinExe</OutputType> |
|||
<TargetFramework>netcoreapp3.1</TargetFramework> |
|||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" /> |
|||
<ProjectReference Include="..\..\src\Avalonia.ReactiveUI\Avalonia.ReactiveUI.csproj" /> |
|||
<ProjectReference Include="..\..\src\Avalonia.Controls.DataGrid\Avalonia.Controls.DataGrid.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<Import Project="..\..\build\SampleApp.props" /> |
|||
<Import Project="..\..\build\ReferenceCoreLibraries.props" /> |
|||
<Import Project="..\..\build\BuildTargets.targets" /> |
|||
</Project> |
|||
@ -0,0 +1,3 @@ |
|||
Compat issues with assembly Avalonia.Base: |
|||
CannotAddAbstractMembers : Member 'protected System.IObservable<Avalonia.AvaloniaPropertyChangedEventArgs> Avalonia.AvaloniaProperty.GetChanged()' is abstract in the implementation but is missing in the contract. |
|||
Total Issues: 1 |
|||
@ -0,0 +1,9 @@ |
|||
using Avalonia.Controls.Primitives; |
|||
|
|||
namespace Avalonia.Controls |
|||
{ |
|||
public abstract class IconElement : TemplatedControl |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
using Avalonia.Media; |
|||
|
|||
namespace Avalonia.Controls |
|||
{ |
|||
public class PathIcon : IconElement |
|||
{ |
|||
static PathIcon() |
|||
{ |
|||
AffectsRender<PathIcon>(DataProperty); |
|||
} |
|||
|
|||
public static readonly StyledProperty<Geometry> DataProperty = |
|||
AvaloniaProperty.Register<PathIcon, Geometry>(nameof(Data)); |
|||
|
|||
public Geometry Data |
|||
{ |
|||
get { return GetValue(DataProperty); } |
|||
set { SetValue(DataProperty, value); } |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,278 @@ |
|||
using System; |
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
using System.Collections.Specialized; |
|||
using System.Diagnostics.CodeAnalysis; |
|||
using System.Linq; |
|||
using Avalonia.Collections; |
|||
|
|||
#nullable enable |
|||
|
|||
namespace Avalonia.Controls.Selection |
|||
{ |
|||
internal class InternalSelectionModel : SelectionModel<object?> |
|||
{ |
|||
private IList? _writableSelectedItems; |
|||
private bool _ignoreModelChanges; |
|||
private bool _ignoreSelectedItemsChanges; |
|||
|
|||
public InternalSelectionModel() |
|||
{ |
|||
SelectionChanged += OnSelectionChanged; |
|||
SourceReset += OnSourceReset; |
|||
} |
|||
|
|||
[AllowNull] |
|||
public IList WritableSelectedItems |
|||
{ |
|||
get |
|||
{ |
|||
if (_writableSelectedItems is null) |
|||
{ |
|||
_writableSelectedItems = new AvaloniaList<object?>(); |
|||
SubscribeToSelectedItems(); |
|||
} |
|||
|
|||
return _writableSelectedItems; |
|||
} |
|||
set |
|||
{ |
|||
value ??= new AvaloniaList<object?>(); |
|||
|
|||
if (value.IsFixedSize) |
|||
{ |
|||
throw new NotSupportedException("Cannot assign fixed size selection to SelectedItems."); |
|||
} |
|||
|
|||
if (_writableSelectedItems != value) |
|||
{ |
|||
UnsubscribeFromSelectedItems(); |
|||
_writableSelectedItems = value; |
|||
SyncFromSelectedItems(); |
|||
SubscribeToSelectedItems(); |
|||
|
|||
if (ItemsView is null) |
|||
{ |
|||
SetInitSelectedItems(value); |
|||
} |
|||
|
|||
RaisePropertyChanged(nameof(WritableSelectedItems)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private protected override void SetSource(IEnumerable? value) |
|||
{ |
|||
if (Source == value) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
object?[]? oldSelection = null; |
|||
|
|||
if (Source is object && value is object) |
|||
{ |
|||
oldSelection = new object?[WritableSelectedItems.Count]; |
|||
WritableSelectedItems.CopyTo(oldSelection, 0); |
|||
} |
|||
|
|||
try |
|||
{ |
|||
_ignoreSelectedItemsChanges = true; |
|||
base.SetSource(value); |
|||
} |
|||
finally |
|||
{ |
|||
_ignoreSelectedItemsChanges = false; |
|||
} |
|||
|
|||
if (oldSelection is null) |
|||
{ |
|||
SyncToSelectedItems(); |
|||
} |
|||
else |
|||
{ |
|||
foreach (var i in oldSelection) |
|||
{ |
|||
var index = ItemsView!.IndexOf(i); |
|||
Select(index); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private void SyncToSelectedItems() |
|||
{ |
|||
if (_writableSelectedItems is object) |
|||
{ |
|||
try |
|||
{ |
|||
_ignoreSelectedItemsChanges = true; |
|||
_writableSelectedItems.Clear(); |
|||
|
|||
foreach (var i in base.SelectedItems) |
|||
{ |
|||
_writableSelectedItems.Add(i); |
|||
} |
|||
} |
|||
finally |
|||
{ |
|||
_ignoreSelectedItemsChanges = false; |
|||
} |
|||
} |
|||
} |
|||
|
|||
private void SyncFromSelectedItems() |
|||
{ |
|||
if (Source is null || _writableSelectedItems is null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
try |
|||
{ |
|||
_ignoreModelChanges = true; |
|||
|
|||
using (BatchUpdate()) |
|||
{ |
|||
Clear(); |
|||
Add(_writableSelectedItems); |
|||
} |
|||
} |
|||
finally |
|||
{ |
|||
_ignoreModelChanges = false; |
|||
} |
|||
} |
|||
|
|||
private void SubscribeToSelectedItems() |
|||
{ |
|||
if (_writableSelectedItems is INotifyCollectionChanged incc) |
|||
{ |
|||
incc.CollectionChanged += OnSelectedItemsCollectionChanged; |
|||
} |
|||
} |
|||
|
|||
private void UnsubscribeFromSelectedItems() |
|||
{ |
|||
if (_writableSelectedItems is INotifyCollectionChanged incc) |
|||
{ |
|||
incc.CollectionChanged += OnSelectedItemsCollectionChanged; |
|||
} |
|||
} |
|||
|
|||
private void OnSelectionChanged(object sender, SelectionModelSelectionChangedEventArgs e) |
|||
{ |
|||
if (_ignoreModelChanges) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
try |
|||
{ |
|||
var items = WritableSelectedItems; |
|||
var deselected = e.DeselectedItems.ToList(); |
|||
var selected = e.SelectedItems.ToList(); |
|||
|
|||
_ignoreSelectedItemsChanges = true; |
|||
|
|||
foreach (var i in deselected) |
|||
{ |
|||
items.Remove(i); |
|||
} |
|||
|
|||
foreach (var i in selected) |
|||
{ |
|||
items.Add(i); |
|||
} |
|||
} |
|||
finally |
|||
{ |
|||
_ignoreSelectedItemsChanges = false; |
|||
} |
|||
} |
|||
|
|||
private void OnSourceReset(object sender, EventArgs e) => SyncFromSelectedItems(); |
|||
|
|||
private void OnSelectedItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) |
|||
{ |
|||
if (_ignoreSelectedItemsChanges) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
if (_writableSelectedItems == null) |
|||
{ |
|||
throw new AvaloniaInternalException("CollectionChanged raised but we don't have items."); |
|||
} |
|||
|
|||
void Remove() |
|||
{ |
|||
foreach (var i in e.OldItems) |
|||
{ |
|||
var index = IndexOf(Source, i); |
|||
|
|||
if (index != -1) |
|||
{ |
|||
Deselect(index); |
|||
} |
|||
} |
|||
} |
|||
|
|||
try |
|||
{ |
|||
using var operation = BatchUpdate(); |
|||
|
|||
_ignoreModelChanges = true; |
|||
|
|||
switch (e.Action) |
|||
{ |
|||
case NotifyCollectionChangedAction.Add: |
|||
Add(e.NewItems); |
|||
break; |
|||
case NotifyCollectionChangedAction.Remove: |
|||
Remove(); |
|||
break; |
|||
case NotifyCollectionChangedAction.Replace: |
|||
Remove(); |
|||
Add(e.NewItems); |
|||
break; |
|||
case NotifyCollectionChangedAction.Reset: |
|||
Clear(); |
|||
Add(_writableSelectedItems); |
|||
break; |
|||
} |
|||
} |
|||
finally |
|||
{ |
|||
_ignoreModelChanges = false; |
|||
} |
|||
} |
|||
|
|||
private void Add(IList newItems) |
|||
{ |
|||
foreach (var i in newItems) |
|||
{ |
|||
var index = IndexOf(Source, i); |
|||
|
|||
if (index != -1) |
|||
{ |
|||
Select(index); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private static int IndexOf(object? source, object? item) |
|||
{ |
|||
if (source is IList l) |
|||
{ |
|||
return l.IndexOf(item); |
|||
} |
|||
else if (source is ItemsSourceView v) |
|||
{ |
|||
return v.IndexOf(item); |
|||
} |
|||
|
|||
return -1; |
|||
} |
|||
} |
|||
} |
|||
@ -1,283 +0,0 @@ |
|||
using System; |
|||
using System.Collections; |
|||
using System.Collections.Specialized; |
|||
using System.ComponentModel; |
|||
using System.Linq; |
|||
using Avalonia.Collections; |
|||
using Avalonia.Controls.Selection; |
|||
|
|||
#nullable enable |
|||
|
|||
namespace Avalonia.Controls.Utils |
|||
{ |
|||
/// <summary>
|
|||
/// Synchronizes an <see cref="ISelectionModel"/> with a list of SelectedItems.
|
|||
/// </summary>
|
|||
internal class SelectedItemsSync : IDisposable |
|||
{ |
|||
private ISelectionModel _selectionModel; |
|||
private IList _selectedItems; |
|||
private bool _updatingItems; |
|||
private bool _updatingModel; |
|||
|
|||
public SelectedItemsSync(ISelectionModel model) |
|||
{ |
|||
_selectionModel = model ?? throw new ArgumentNullException(nameof(model)); |
|||
_selectedItems = new AvaloniaList<object?>(); |
|||
SyncSelectedItemsWithSelectionModel(); |
|||
SubscribeToSelectedItems(_selectedItems); |
|||
SubscribeToSelectionModel(model); |
|||
} |
|||
|
|||
public ISelectionModel SelectionModel |
|||
{ |
|||
get => _selectionModel; |
|||
set |
|||
{ |
|||
if (_selectionModel != value) |
|||
{ |
|||
value = value ?? throw new ArgumentNullException(nameof(value)); |
|||
UnsubscribeFromSelectionModel(_selectionModel); |
|||
_selectionModel = value; |
|||
SubscribeToSelectionModel(_selectionModel); |
|||
SyncSelectedItemsWithSelectionModel(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public IList SelectedItems |
|||
{ |
|||
get => _selectedItems; |
|||
set |
|||
{ |
|||
value ??= new AvaloniaList<object?>(); |
|||
|
|||
if (_selectedItems != value) |
|||
{ |
|||
if (value.IsFixedSize) |
|||
{ |
|||
throw new NotSupportedException( |
|||
"Cannot assign fixed size selection to SelectedItems."); |
|||
} |
|||
|
|||
UnsubscribeFromSelectedItems(_selectedItems); |
|||
_selectedItems = value; |
|||
SubscribeToSelectedItems(_selectedItems); |
|||
SyncSelectionModelWithSelectedItems(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
UnsubscribeFromSelectedItems(_selectedItems); |
|||
UnsubscribeFromSelectionModel(_selectionModel); |
|||
} |
|||
|
|||
private void SyncSelectedItemsWithSelectionModel() |
|||
{ |
|||
_updatingItems = true; |
|||
|
|||
try |
|||
{ |
|||
_selectedItems.Clear(); |
|||
|
|||
if (_selectionModel.Source is object) |
|||
{ |
|||
foreach (var i in _selectionModel.SelectedItems) |
|||
{ |
|||
_selectedItems.Add(i); |
|||
} |
|||
} |
|||
} |
|||
finally |
|||
{ |
|||
_updatingItems = false; |
|||
} |
|||
} |
|||
|
|||
private void SyncSelectionModelWithSelectedItems() |
|||
{ |
|||
_updatingModel = true; |
|||
|
|||
try |
|||
{ |
|||
if (_selectionModel.Source is object) |
|||
{ |
|||
using (_selectionModel.BatchUpdate()) |
|||
{ |
|||
SelectionModel.Clear(); |
|||
Add(_selectedItems); |
|||
} |
|||
} |
|||
} |
|||
finally |
|||
{ |
|||
_updatingModel = false; |
|||
} |
|||
} |
|||
|
|||
private void SelectedItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) |
|||
{ |
|||
if (_updatingItems) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
if (_selectedItems == null) |
|||
{ |
|||
throw new AvaloniaInternalException("CollectionChanged raised but we don't have items."); |
|||
} |
|||
|
|||
void Remove() |
|||
{ |
|||
foreach (var i in e.OldItems) |
|||
{ |
|||
var index = IndexOf(SelectionModel.Source, i); |
|||
|
|||
if (index != -1) |
|||
{ |
|||
SelectionModel.Deselect(index); |
|||
} |
|||
} |
|||
} |
|||
|
|||
try |
|||
{ |
|||
using var operation = SelectionModel.BatchUpdate(); |
|||
|
|||
_updatingModel = true; |
|||
|
|||
switch (e.Action) |
|||
{ |
|||
case NotifyCollectionChangedAction.Add: |
|||
Add(e.NewItems); |
|||
break; |
|||
case NotifyCollectionChangedAction.Remove: |
|||
Remove(); |
|||
break; |
|||
case NotifyCollectionChangedAction.Replace: |
|||
Remove(); |
|||
Add(e.NewItems); |
|||
break; |
|||
case NotifyCollectionChangedAction.Reset: |
|||
SelectionModel.Clear(); |
|||
Add(_selectedItems); |
|||
break; |
|||
} |
|||
} |
|||
finally |
|||
{ |
|||
_updatingModel = false; |
|||
} |
|||
} |
|||
|
|||
private void Add(IList newItems) |
|||
{ |
|||
foreach (var i in newItems) |
|||
{ |
|||
var index = IndexOf(SelectionModel.Source, i); |
|||
|
|||
if (index != -1) |
|||
{ |
|||
SelectionModel.Select(index); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private void SelectionModelPropertyChanged(object sender, PropertyChangedEventArgs e) |
|||
{ |
|||
if (e.PropertyName == nameof(ISelectionModel.Source)) |
|||
{ |
|||
if (_selectedItems.Count > 0) |
|||
{ |
|||
SyncSelectionModelWithSelectedItems(); |
|||
} |
|||
else |
|||
{ |
|||
SyncSelectedItemsWithSelectionModel(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private void SelectionModelSelectionChanged(object sender, SelectionModelSelectionChangedEventArgs e) |
|||
{ |
|||
if (_updatingModel || _selectionModel.Source is null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
try |
|||
{ |
|||
var deselected = e.DeselectedItems.ToList(); |
|||
var selected = e.SelectedItems.ToList(); |
|||
|
|||
_updatingItems = true; |
|||
|
|||
foreach (var i in deselected) |
|||
{ |
|||
_selectedItems.Remove(i); |
|||
} |
|||
|
|||
foreach (var i in selected) |
|||
{ |
|||
_selectedItems.Add(i); |
|||
} |
|||
} |
|||
finally |
|||
{ |
|||
_updatingItems = false; |
|||
} |
|||
} |
|||
|
|||
private void SelectionModelSourceReset(object sender, EventArgs e) |
|||
{ |
|||
SyncSelectionModelWithSelectedItems(); |
|||
} |
|||
|
|||
|
|||
private void SubscribeToSelectedItems(IList selectedItems) |
|||
{ |
|||
if (selectedItems is INotifyCollectionChanged incc) |
|||
{ |
|||
incc.CollectionChanged += SelectedItemsCollectionChanged; |
|||
} |
|||
} |
|||
|
|||
private void SubscribeToSelectionModel(ISelectionModel model) |
|||
{ |
|||
model.PropertyChanged += SelectionModelPropertyChanged; |
|||
model.SelectionChanged += SelectionModelSelectionChanged; |
|||
model.SourceReset += SelectionModelSourceReset; |
|||
} |
|||
|
|||
private void UnsubscribeFromSelectedItems(IList selectedItems) |
|||
{ |
|||
if (selectedItems is INotifyCollectionChanged incc) |
|||
{ |
|||
incc.CollectionChanged -= SelectedItemsCollectionChanged; |
|||
} |
|||
} |
|||
|
|||
private void UnsubscribeFromSelectionModel(ISelectionModel model) |
|||
{ |
|||
model.PropertyChanged -= SelectionModelPropertyChanged; |
|||
model.SelectionChanged -= SelectionModelSelectionChanged; |
|||
model.SourceReset -= SelectionModelSourceReset; |
|||
} |
|||
|
|||
private static int IndexOf(object? source, object? item) |
|||
{ |
|||
if (source is IList l) |
|||
{ |
|||
return l.IndexOf(item); |
|||
} |
|||
else if (source is ItemsSourceView v) |
|||
{ |
|||
return v.IndexOf(item); |
|||
} |
|||
|
|||
return -1; |
|||
} |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue