Add samples how code looks in WPF and Avalonia

This commit is contained in:
Andrii Kurdiumov 2023-05-21 00:01:16 +06:00
Родитель 4e7a61f462
Коммит 9c82843945
4 изменённых файлов: 202 добавлений и 1 удалений

Просмотреть файл

@ -51,3 +51,115 @@ Avalonia is in general very similar to WPF, but you will find differences. Here
{% content-ref url="rendertransforms-and-rendertransformorigin.md" %}
[rendertransforms-and-rendertransformorigin.md](rendertransforms-and-rendertransformorigin.md)
{% endcontent-ref %}
# Dispatcher changes
If you use `Application.Current.Dispatcher`, you should use `Dispatcher.UIThread` instead which provide similar facilities.
**WPF**
```
Application.Current.Dispatcher.InvokeAsync(handler, DispatcherPriority.Background);
```
**Avalonia**
```
Dispatcher.UIThread.InvokeAsync(handler, DispatcherPriority.Background);
```
If you previously access dispatcher on the control itself, you should use global static instance `Dispatcher.UIThread` too.
**WPF**
```
this.Dispatcher.InvokeAsync(handler, DispatcherPriority.Background);
```
**Avalonia**
```
Dispatcher.UIThread.InvokeAsync(handler, DispatcherPriority.Background);
```
In more details, it's explained in the [Accessing the UI thread](../../guides/basics/accessing-the-ui-thread.md) article.
# Visibility of elements
WPF has uses `Visibility` property which can be `Collapsed`, `Hidden` or `Visible`. Avalonia uses simpler and more intuitive model `bool IsVisible`.
# Binding
**WPF**
```
<TextBox Name="MyTextbox" Text="{Binding ElementName=searchTextBox, Path=Text}"" />
```
**Avalonia**
```
<TextBox Name="MyTextbox" Text="{Binding #searchTextBox.Text}" />
```
# Handling attachment to visual tree
There no events like `Loaded`/`Unloaded` in Avalonia, but you can override `OnAttachedToVisualTree`/`OnDetachedFromVisualTree` on the control, to know when control attached to virtual tree, or detatched from it. Alternatively you can use `TemplateApplied` instead of `Loaded` event.
**WPF**
```
Unloaded += OnControl_Unloaded;
Loaded += OnControl_Loaded;
private void OnControl_Loaded(object sender, RoutedEventArgs e)
{
// Handle control loaded event.
}
private void OnControl_Unloaded(object sender, RoutedEventArgs e)
{
// Handle control unload event.
}
```
**Avalonia**
```
TemplateApplied += OnControl_Loaded;
private void BuildControl_Loaded(object sender, RoutedEventArgs e)
{
}
// or
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
// Handle control loaded event.
}
// Use this instead of Unloaded event.
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
{
// Handle control unload event.
}
```
That mean that you cannot subscribe to tree attachment/detachment events for other controls.
# Tooltips
Avalonia controls does not have `ToolTip` property like WPF. Instead you should use `ToolTip.Tip`
**WPF**
```csharp
<Button ToolTip="Save file as..." />
```
**Avalonia**
```csharp
<Button ToolTip.Tip="Save file as..." />
```
# TextRun decorations
**WPF**
```csharp
TextRunProperties.SetTextDecorations(TextDecorations.Underline);
```
**Avalonia**
```csharp
TextRunProperties.Underline = true;
```

Просмотреть файл

@ -2,3 +2,29 @@
The Avalonia equivalent of `DependencyProperty` is `StyledProperty`, however Avalonia [has a richer property system than WPF](https://docs.avaloniaui.net/docs/authoring-controls/defining-properties), and includes `DirectProperty` for turning standard CLR properties into Avalonia properties. The common base class of `StyledProperty` and `DirectProperty` is `AvaloniaProperty`.
If your dependency property uses `FrameworkPropertyMetadataOptions.AffectsMeasure` now you should use `AffectsMeasure<TControl>(MyProperty)` to obtain desired effect.
**WPF**
```csharp
// SplitterPanel control
public static readonly DependencyProperty OrientationProperty =
DependencyProperty.Register(
"Orientation",
typeof(Orientation),
typeof(SplitterPanel),
new FrameworkPropertyMetadata(
Orientation.Horizontal,
FrameworkPropertyMetadataOptions.AffectsMeasure));
```
**Avalonia**
```csharp
// SplitterPanel control
public static readonly StyledProperty<Orientation> OrientationProperty =
AvaloniaProperty.Register<SplitterPanel, Orientation>(nameof(Orientation), Orientation.Horizontal);
static SplitterPanel()
{
AffectsMeasure<SplitterPanel>(OrientationProperty);
}
```

Просмотреть файл

@ -1,4 +1,14 @@
# ItemsControl
In WPF, `ItemsControl` and derived classes such as `ListBox` have two separate items properties: `Items` and `ItemsSource`. Avalonia however just has a single one: `Items`.
In WPF, `ItemsControl` and derived classes such as `ListBox` have two separate items properties: `Items` and `ItemsSource`. Avalonia however just has a single one: `Items` which is same as WPF `ItemsSource` property.
## Before
```csharp
contextMenu.Items.Add(runItem);
```
## After
```csharp
var list = contextMenu.Items as IList;
list?.Add(runItem);
```

Просмотреть файл

@ -4,3 +4,56 @@ Listening to changes on DependencyProperties in WPF can be complex. When you reg
In Avalonia, there is no `PropertyChangedCallback` at the time of registration, instead a class listener is [added to the control's static constructor in much the same way that event class listeners are added](https://docs.avaloniaui.net/docs/data-binding/binding-from-code#subscribing-to-a-property-on-any-object).
As side effect of this change, you may need to dispatch events yourself.
**WPF**
```csharp
treeView.SelectedItemChanged += TreeView_SelectedItemChanged;
// ...
private void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
var item = treeView.SelectedItem;
// work with selected item.
}
```
**Avalonia**
```csharp
treeView.PropertyChanged += TreeView_SelectedItemChanged;
// ...
private void TreeView_SelectedItemChanged(object sender, AvaloniaPropertyChangedEventArgs e)
{
if (e.Property != TreeView.SelectedItemProperty) return;
var item = treeView.SelectedItem;
// work with selected item.
}
```
Even plain text box should be handled in same way.
**WPF**
```csharp
searchTextBox.TextChanged += new TextChangedEventHandler(searchTextBox_TextChanged);
private void searchTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
// handle text change
}
```
**Avalonia**
```csharp
searchTextBox.PropertyChanged += searchTextBox_TextChanged;
// ...
private void searchTextBox_TextChanged(object sender, AvaloniaPropertyChangedEventArgs e)
{
if (e.Property != TextBox.TextProperty) return;
// handle text change
}
```