Add samples how code looks in WPF and Avalonia
This commit is contained in:
Родитель
4e7a61f462
Коммит
9c82843945
|
@ -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
|
||||
}
|
||||
```
|
||||
|
|
Загрузка…
Ссылка в новой задаче