Обновление с версии 0.10
Avalonia 11 introduces a number of breaking changes from 0.10. The following guide converse the most commonly-encountered changes and gives solutions for them.
Обновление проекта
- Обновите пакеты Avalonia до версии 11.x
- Themes больше не находятся в пакете
Avalonia.Desktop
, поэтому вам необходимо добав ить один из следующих:Avalonia.Themes.Fluent
Avalonia.Themes.Simple
- Удалите ссылку на пакет
XamlNameReferenceGenerator
- теперь Avalonia по-умолчанию имеет встроенный генератор. - Если требуется, обновите
<LangVersion>
хотя бы до 9 версии, чтобы использоватьInit-only Properties
- Если вы хотите использовать те же шрифты, что и в версии
0.10
, то добавьте пакетAvalonia.Fonts.Inter
, а также.WithInterFont()
вapp builder
. С версии 11.0, по-умолчанию не поддерживаются сторонние шрифты.
Theme Handling
Для версии 0.10
, тема указывается внутри тега Application.Styles
в файле Application.axaml
.
Пример:
<Application.Styles>
<FluentTheme Mode="Light"/>
</Application.Styles>
В примере выше, для тега FluentTheme
указывается атрибут Mode
, через который задается режим темы.
Он может быть как Light
, так и Dark
.
Для улучшения управления темами, в тег Application
был добавлен атрибут RequestedThemeVariant
.
Он используется для установки темы приложения, в обход системной.
Если требуется, чтобы приложение соответствовала системной теме, то необходимо установить значение Default
.
Другие доступные варианты: Light
и Dark
.
Пример использования:
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ILoveAvaloniaUI.App"
xmlns:local="using:ILoveAvaloniaUI"
RequestedThemeVariant="Default">
Тег FluentTheme
больше не требует обязательного указания атрибута Mode
.
<Application.Styles>
<FluentTheme />
</Application.Styles>
Theme Dictionary and Theme Variant
Согласно PR #8166, теперь метод Styles.TryGetResource
требует, чтобы параметр ThemeVariant
был nullable
.
Это позволяет указывать темы Light
, Dark
и Default
.
Параметр ThemeVariant.Default
позволяет указать тему по-умолчанию, если искомый вариант не найден.
Помимо встроенных значений Light
, Dark
и Default
, любое другое значение объекта можно использовать в качестве ключа
(поскольку оно заключено в структуру ThemeVariant(object key)
).
Расширение разметки {x:Static}
, можно использовать для определения тем в качестве статических,
что позволит ссылаться на них в коде XAML.
// Before
bool TryGetResource(object key, out object? value)
// Avalonia v11
bool TryGetResource(object key, ThemeVariant? theme, out object? value)
System.Reactive/Observables
Avalonia больше не зависит от System.Reactive
. Если вы используете его, то необходимо добави ть пакет System.Reactive
в ваш проект.
Если вы не используете весь System.Reactive
, но при этом хотите использовать простые подписки IObservable<T>
,
то можно использовать служебный класс Avalonia AnonymousObserver<T>
, например:
observable.Subscribe(new AnonymousObserver<string>(() => { /* Code to execute when the observable changes. */ }));
Если вам требуется подписаться на изменения свойств или событий, то вместо observables
можно использовать AddClassHandler
.
Updating Interfaces
Множество интерфейсов были убраны в Avalonia 11. У вас не должно быть проблем, чтобы используя глобальный поиск/замену, провести указанную ниже замену интерфейса на реализацию: interfaces with its concrete type:
IAvaloniaObject
->AvaloniaObject
IBitmap
->Bitmap
IContentPresenter
->ContentPresenter
IControl
->Control
IInteractive
->Interactive
IItemsPresenter
->ItemsPresenter
ILayoutable
->Layoutable
IPanel
->Panel
IStyledElement
->StyledElement
ITemplatedControl
->TemplatedControl
IVisual
->Visual
Если вы используете собственный интерфейсы на базе одного из вышеперечисленных, то необходимо удалить базовый интерфейс и провести приведение к конкретному классу.
Опционально (рекомендуем):
Интерфейс IStyleable
стал Deprecated
, В версии 0.10.x
, для переопределения ключа стиля Control
,
вам требовалось переопределять IStyleable
и добавлять явную реализацию для StyleKey
:
class MyButton : Button, IStyleable
{
Type IStyleable.StyleKey => typeof(Button);
}
С версии 11
, при использовании IStyleable
, вы получите предупреждение Deprecated
.
Теперь следует делать так:
class MyButton : Button
{
protected override Type StyleKeyOverride => typeof(Button);
}
Подробнее в #11380.
Views
Теперь ваши View
, которые представлены парами .axaml
/.axaml.cs
(или .xaml
/.xaml.cs
),
имеют автоматически-сгенерированный код на C#.
Для этого?
- В файле
.cs
, пометьте класс какpartial
- Удалите метод
private void InitializeComponent()
- НЕ удаляйте вызов
InitializeComponent()
из конструктора: данный метод теперь генерируется автоматически, но все также необходим. - Удалите вызов
this.AttachDevTools()
из конструктора. ТеперьInitializeComponent
имеет параметр, который управляет подключениемDevTools
в режиме отладки, по-умолчанию он включен.
Раньше, чтобы найти именнованый элемент объявленный в XAML файлы, нужен был вызов this.FindControl<T>(string name)
или this.GetControl<T>(string name)
. Сейчас это не обязательно - XAML элементы с выставленными
Name
или x:Name
атрибутами будут автоматически сгенерированны для доступа в C# классах (так же как это работало в WPF и UWP).
Обратите внимание, что автомамтически, код генерируется только для C#. Для F# изменений не было.
ItemsControl
ItemsControl
, а также его пр оизводные классы, такие как ListBox
и ComboBox
,
теперь имеют свойства Items
и ItemsSource
, по-аналогии с WPF/UWP.
Items
- это коллекция, доступная только для чтения, предварительно заполняется.
ItemsSource
- это коллекция, которая' используется для чтения и записи, по-умолчанию равна null
.
Замените все привязки к Items
на ItemsSource
:
<ListBox Items="{Binding Items}">
Стало:
<ListBox ItemsSource="{Binding Items}">
Дополнительно:
-
Был удален
ListBox.VirtualizationMode
, теперь виртуализация указывается черезItemsPanel
:- Для отключения виртуализации, используйте
StackPanel
. - Для включения виртуализации, используйте
VirtualizingStackPanel
.
- Для отключения виртуализации, используйте
-
Был удален
Carousel.IsVirtualizing
, теперь дляCarousel
всегда используется виртуализация. -
Item container lookup перенесен в
ItemsControl
, как в UWP (старые методы остались в ItemContainerGenerator, но помечены как [Obsolete]):ItemsControl.ContainerFromIndex(object item)
ItemsControl.IndexFromContainer(Control container)
-
В
ItemsPresenter
были удалены свойстваItems
иItemTemplate
. Привязку шаблона к ним, можно просто удалить.
Classes
StyledElement.Classes
теперь доступен только для чтения.
Нижеуказанный код инициализации:
var c = new Control
{
Classes = new Classes("foo", "bar"),
};
Замените на:
var c = new Control
{
Classes = { "foo", "bar" },
};
Для работы с Classes
вне инициализации объекта, следует использовать стандартные функции IList<string>
.
Подробнее в #11013.
Windows
API TopLEvel.PlatformImpl
больше недоступно для Controls, таких как Window
.
Соответствующие методы были перемещены в TopLevel
, WindowBase
или Window
:
window.PlatformImpl.Handle
->window.TryGetPlatformHandle()
window.PlatformImpl.BeginMove(e)
->window.BeginMove()
window.PlatformImpl.Resized
->window.Resized
AssetLoader
Интерфейс IAssetLoader
больше не доступен. Используйте статический класс AssetLoader
:
var assets = AvaloniaLocator.Current.GetService<IAssetLoader>();
var bitmap = new Bitmap(assets.Open(new Uri(uri)));
Стало:
var bitmap = new Bitmap(AssetLoader.Open(new Uri(uri)));
OnPropertyChanged
Виртуальный метод AvaloniaObject.OnPropertyChanged
, больше не использует дженерики. Замените
protected override void OnPropertyChanged<T>(AvaloniaPropertyChangedEventArgs<T> change)
на
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
Также изменился способ старых и новых значений из AvaloniaPropertyChangedEventArgs
без boxing
:
- Замените
change.NewValue.GetValueOrDefault<T>()
наchange.GetNewValue<bool>()
- Замените
change.OldValue.GetValueOrDefault<T>()
наchange.GetOldValue<bool>()
- Можно использовать
change.GetOldAndNewValue<T>()
для получения обеих значений.
See #7980 for more information.
Events
Нижеуказанный события были переименованы:
PointerEnter
->PointerEntered
PointerLeave
->PointerExited
ContextMenu
ContextMenuClosing
->Closing
ContextMenuOpening
->Opening
MenuBase
MenuClosed
->Closed
MenuOpened
->Opened
RoutedEventArgs.Source
поменяли тип с IInteractive
на object
: сделайте приведение к конкретному типу, скажем Control
, и используйте.
Layout
Раньше, чтобы вызвать полный перепросчет макета элементов, нужно было вытащить корневой элемент и на нем вызвать следующий код:
((ILayoutRoot)control).LayoutManager.ExecuteLayout();
Сейчас же LayoutManager
больше не доступен из ILayoutRoot
. Вместо него испоьзуйте метод UpdateLayout
на любом Control, как в WPF/UWP:
control.UpdateLayout();
ILayoutable
использовался в версии 0.10.x
для доступа к Constraints
и Arrange Bounds
.
Теперь они доступны через LayoutInformation
:
Size? LayoutInformation.GetPreviousMeasureConstraint(Layoutable control)
Rect? LayoutInformation.GetPreviousArrangeBounds(Layoutable control)