Skip to content

Commit

Permalink
Merge pull request #578 from hiddenblue/main
Browse files Browse the repository at this point in the history
Add and update some zh-CN translation
  • Loading branch information
rabbitism authored Nov 22, 2024
2 parents 1459c4f + 6d51f02 commit 9d26a46
Show file tree
Hide file tree
Showing 9 changed files with 536 additions and 21 deletions.
11 changes: 0 additions & 11 deletions i18n/zh-Hans/docusaurus-plugin-content-docs/current/community.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,5 @@ import GitterChatScreenshot from '/img/gitbook-import/assets/image (37) (1) (1).
您可以在[这里](https://t.me/Avalonia)访问 Telegram 聊天室。
:::

## Gitter

<img src={GitterLogoScreenshot} alt="" data-size="original"/>

我们在 Gitter 平台上运营一个英语聊天室。

<img src={GitterChatScreenshot} alt="" />

:::info
您可以在[这里](https://gitter.im/AvaloniaUI/Avalonia)使用 Gitter 在浏览器中访问聊天室。
:::


Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
---
id: focus
title: 焦点
---

import DirectionalNavigationScreenshot from '/img/concepts/input/directional-navigation.gif';

# 焦点
焦点是指预期接收键盘输入的 `InputElement`,通常通过视觉指示器来区分。最熟悉的例子是包含闪烁光标的 `TextBox`,但像 `Button``Slider` 这样的非文本控件也参与焦点管理。

## IsFocused 和 Focusable

`IsFocused` 是一个只读属性,用于跟踪 `InputElement` 的焦点状态。
`Focusable` 属性启用或禁用 `InputElement` 的焦点能力。无法获得焦点的元素仍然可以通过指针进行交互,因此应尽量确保提供具备功能性的键盘等效操作(如快捷键)。

## 显式聚焦

要显式地将焦点分配给任何 `InputElement`,可以在代码中调用其 `.Focus()` 方法。可选地,可以指定 `NavigationMethod``KeyModifiers` 以模拟特定的焦点导航流程。显式聚焦通常用于在加载数据输入表单时聚焦特定的 `InputElement`,或者在当前输入满足后程序化地移动到下一个 `InputControl`

| NavigationMethod | 触发描述 |
|:-----------------|:---------------------------|
| Tab | 按下 Tab 键 |
| Pointer | 指针交互 |
| Directional | 2D 方向性 (`XYFocus`) |
| Unspecified | 默认 |

## 焦点事件

`InputElement` 暴露了 `GotFocus``LostFocus` 事件。`GotFocusEventArgs` 包含触发焦点导航的 `NavigationMethod``KeyModifiers`

## 焦点伪类

这些伪类在为 `Focusable``Control` 设置样式时非常有用。

| 伪类 | 描述 |
|:---------------|----------------------------------------------------------------|
| :focus | 控件具有焦点。 |
| :focus-within | 控件具有焦点或包含具有焦点的子元素。 |
| :focus-visible | 控件具有焦点并应显示视觉指示器。 |

:::tip
`FocusAdorner` 属性用于在 `:focus-visible``Control` 周围显示默认的焦点视觉效果,通常是 `Border`。当使用 `:focus-visible` 显示自定义视觉指示器时,将 `FocusAdorner` 设置为 `null` 可避免显示重复的指示器。
:::

## FocusManager

`FocusManager` 提供对焦点功能的全局访问,例如检索当前聚焦的元素或清除焦点。有关更多信息,请参阅 [FocusManager 文档](../services/focus-manager)

## Tab 焦点导航

当用户在键盘上按下 Tab 键时,会发生 Tab 焦点导航。将 `IsTabStop` 属性设置为 `true``InputElement` 将可用于 Tab 焦点导航。`TabIndex` 指定了优先级,数值较低的元素会先被导航到。当多个控件的 `TabIndex` 相等时,优先级基于视觉树遍历顺序。
`KeyboardNavigation.TabNavigation` 附加属性可以为作为容器的任何 `InputElement` 设置 `KeyboardNavigationMode`,并修改其 Tab 导航特性。
| KeyboardNavigationMode | 容器项遍历 |
|:-----------------------|:----------------------------------------------------------|
| Continue | 继续遍历项目并进入下一个容器 |
| Cycle | 在自身项目中循环遍历 |
| Contained | 停止在开始/结束项 |
| Once | 容器和子元素仅作为一组获得焦点一次 |
| None | 项目不会通过 Tab 导航获得焦点 |
| Local | 仅考虑本地子树中的 `TabIndex` |

## 方向性焦点导航 <MinVersion version="11.1" />

通过 `XYFocus` 实现的焦点导航是一种 2D 方向性方案,允许从聚焦的控件向另一个控件进行空间导航,方向包括左、右、上、下。默认情况下,`XYFocus.NavigationModes` 被设置为允许 `Gamepad``Remote` 导航。

| KeyDeviceType | 设备 |
|:--------------|:------------------------------------------|
| Disabled | 任何按键设备的 XY 导航已禁用。 |
| Keyboard | 可以使用键盘箭头键。 |
| Gamepad | 可以使用游戏手柄的 DPad。 |
| Remote | 可以使用遥控器。 |
| Enabled | 所有设备都可以使用。 |

支持游戏手柄输入的设备包括可以原生发送这些输入的设备,如 Android 和 Tizen。然而,Avalonia 当前缺乏跨平台的游戏手柄 API,因此无法广泛地开箱即用地支持。

### 导航策略

当启用 2D 方向性导航时,将使用一种消歧策略来选择导航目标。
| XYFocusNavigationStrategy | 导航目标 |
|:----------------------------|:------------------------------------------------------------------------------|
| Auto | 继承自祖先的策略。如果没有任何祖先指定,则使用Projection策略。 |
| Projection | 在导航方向上投影一条线时遇到的第一个元素。 |
| NavigationDirectionDistance | 最接近导航线轴的元素。 |
| RectilinearDistance | 基于最短曼哈顿距离的最近元素。 |

### 显式导航

`XYFocus` 允许每个控件在按下某个方向时指定显式的导航目标,通过 `XYFocus.Up``XYFocus.Down``XYFocus.Left``XYFocus.Right`。这优先于任何导航策略。

:::warning
焦点参与尚未实现,因此将方向性焦点导航与自身处理方向输入的控件结合使用可能会有一些限制,尤其是在视觉效果方面。
:::

### 示例

以下示例展示了如何在 `WrapPanel` 中使用方向性焦点导航。它显式地允许从第一个元素导航到最后一个元素,反之亦然。

`Slider` 提供了一个混合导航和控件交互的示例。在桌面平台上,当 `Slider` 获得焦点时按下 Enter 键将开始一个交互过程,用户将修改 `Slider.Value` 而不是导致导航。再次按下 Enter 键将结束交互并恢复方向性焦点导航。

```xml
<Window
XYFocus.NavigationModes="Enabled"
XYFocus.UpNavigationStrategy="Projection"
XYFocus.DownNavigationStrategy="Projection"
XYFocus.LeftNavigationStrategy="Projection"
XYFocus.RightNavigationStrategy="Projection">
<Grid>
<WrapPanel>
<Button x:Name="first"
Content="First"
XYFocus.Left="{Binding #last}" />
<Button Content="Second" />
<Button Content="Third" />

<Slider Width="100" Maximum="100" />

<Button Content="Fourth" />
<Button x:Name="last"
Content="Last"
XYFocus.Right="{Binding #first}" />
</WrapPanel>
</Grid>
</Window>
```

<img src={DirectionalNavigationScreenshot} alt="Directional Navigation Example"/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
---
id: markupextensions
title: Markup Extensions
---

`Markup Extension` 允许在 XAML 中以方便、可重用的语法对目标属性的 setter 逻辑进行基于代码的自定义。大括号用于区分普通文本的使用。
Avalonia 提供了以下内容:
| MarkupExtension | 分配给属性 |
|--------------------------------------------------------------------------------------------------|--------------------------------------------------------------------|
| [StaticResource](/docs/guides/styles-and-resources/resources#static-resource) | 一个存在的有键值的资源,并且不会在更改时更新 |
| [DynamicResource](/docs/guides/styles-and-resources/resources#using-resources) | 延迟加载的键资源,会在更改时更新 |
| Binding | 基于默认的绑定偏好:编译或反射 |
| [CompiledBinding](/docs/basics/data/data-binding/compiled-bindings#compiledbinding-markup) | 基于编译的绑定 |
| [ReflectionBinding](/docs/basics/data/data-binding/compiled-bindings#reflectionbinding-markup) | 基于反射的绑定 |
| [TemplateBinding](/docs/guides/custom-controls/how-to-create-templated-controls#data-binding) | 基于简化的绑定,仅在 `ControlTemplate` 内使用 |
| [OnPlatform](/docs/guides/platforms/platform-specific-code/xaml#onplatform-markup-extension) | 当处于指定平台时有条件地使用 |
| [OnFormFactor](/docs/guides/platforms/platform-specific-code/xaml#onformfactor-markup-extension) | 当处于指定因素时有条件地使用 |

## 编译器内在函数

这些技术上不属于 `MarkupExtension`,而是 XAML 编译器的一部分,但 和XAML 语法相同。

| 内在函数 | 分配给属性 |
|-----------|-----------------------|
| x:True | `true` 字面量 |
| x:False | `false` 字面量 |
| x:Null | `null` 字面量 |
| x:Static | 静态成员值 |
| x:Type | `System.Type` 字面量 |

`x:True``x:False` 字面量在目标绑定属性为 `object` 且需要提供布尔值的情况下有用。在这些缺少类型信息的场景中,提供 "True" 仍然是一个字符串。

```xml
<Button Command="{Binding SetStateCommand}" CommandParameter="{x:True}" />
```

## 创建 MarkupExtensions

派生自 `MarkupExtension` 或添加以下通过鸭子类型支持的签名之一:

```csharp
T ProvideValue();
T ProvideValue(IServiceProvider provider);
object ProvideValue();
object ProvideValue(IServiceProvider provider);
```

当使用强类型而不是 `object` 时,如果在 XAML 中构造参数、属性或 `ProvideValue` 中的返回值不匹配,将会收到编译时错误。当返回 `object` 时,实际返回的类型必须与目标属性的类型匹配,否则运行时会抛出 `InvalidCastException`

### 接收字面量参数

当需要参数时,使用构造函数按顺序接收每个参数。

对于可选或无序参数,使用属性代替。允许混合使用多个构造函数,包括无参数构造函数。

```csharp
public class MultiplyLiteral
{
private readonly double _first;
private readonly double _second;

public double? Third { get; set; }
public MultiplyLiteral(double first, double second)
{
_first = first;
_second = second;
}
public double ProvideValue(IServiceProvider provider)
{
return First * Second * Third ?? 1;
}
}
```
```xml
<TextBlock Text="This has FontSize=40" FontSize="{namespace:MultiplyLiteral 10, 8, Third=0.5}" />
```

### 从绑定接收参数

常见的场景是希望转换来自绑定的数据并更新目标属性。当所有参数都来自绑定时,通过创建一个带有 `IMultiValueConverter``MultiBinding` 来实现这一点相对简单。在下面的示例中,`MultiplyBinding` 需要两个绑定参数。如果需要混合字面量和绑定参数,创建一个 `IMultiValueConverter` 可以允许传递字面量作为构造函数或 `init` 参数。`BindingBase` 允许使用 `CompiledBinding``ReflectionBinding`,但不允许使用字面量。

```csharp
public class MultiplyBinding
{
private readonly BindingBase _first;
private readonly BindingBase _second;
public MultiplyBinding(BindingBase first, BindingBase second)
{
_first = first;
_second = second;
}
public object ProvideValue()
{
var mb = new MultiBinding()
{
Bindings = new[] { _first, _second },
Converter = new FuncMultiValueConverter<double, double>(doubles => doubles.Aggregate(1d, (x, y) => x * y))
};
return mb;
}
}
```

```xml
<TextBlock FontSize="{local:MultiplyBinding {Binding Multiplier}, {Binding Multiplicand}}"
Text="MarkupExtension with Bindings!" />
```

:::info
另一种方法是返回 `IObservable<T>.ToBinding()`
:::

### 返回参数

为了使 `MarkupExtension` 兼容多种目标属性类型,返回 `object` 并分别处理每种支持的类型。

```csharp
public object ProvideValue(IServiceProvider provider)
{
var target = (IProvideValueTarget)provider.GetService(typeof(IProvideValueTarget))!;
var targetProperty = target.TargetProperty as AvaloniaProperty;
var targetType = targetProperty?.PropertyType;
double result = First * Second * (Third ?? 1);
if (targetType == typeof(double))
return result;
else if (targetType == typeof(float))
return (float)result;
else if (targetType == typeof(int))
return (int)result;
else
throw new NotSupportedException();
}
```

构造函数也可以使用 `object` 方法接收参数类型,但编译时错误同样会变成运行时异常。

### MarkupExtension 属性注解

* `[ConstructorArgument]` - 关联属性可以通过构造函数参数初始化,并且如果使用了构造函数,则在 XAML 序列化时应忽略该属性。
* `[MarkupExtensionOption]`, `[MarkupExtensionDefaultOption]` - 与 `ShouldProvideOption` 一起使用,查看 `OnPlatform``OnFormFactor` 的源代码以获取示例。
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public class ViewLocator : IDataTemplate

## Using the View Locator

By default, the View Locator is referenced in App.axaml as a DataTemplate, in the content of the `Application.DataTemplates` XAML tag. Ensure that its appropriate 'using' statement is in the `xmlns:local` property of the Application root tag.
默认情况下,视图定位器在 App.axaml 中作为 DataTemplate 引用,位于 `Application.DataTemplates XAML` 标签的内容中。确保在应用程序根标签的 `xmlns:local` 属性中包含其适当的 using 语句。

```xaml
<Application xmlns="https://github.com/avaloniaui"
Expand All @@ -63,6 +63,7 @@ By default, the View Locator is referenced in App.axaml as a DataTemplate, in th
xmlns:local="using:LearningAvalonia"
RequestedThemeVariant="Default">
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
<!-- "Default" ThemeVariant 是取决于系统的主题变体属性,"Dark" 和 "Light" 是另外可用的选项 -->
<Application.DataTemplates>
<local:ViewLocator />
</Application.DataTemplates>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@ id: install
title: 安装
---

## 预安装

请先安装您选择的受支持的IDE。Avalonia 支持 Visual Studio、Rider 和 Visual Studio Code。

## 安装 Avalonia UI 模板

开始使用 Avalonia 的最佳方式是使用模板创建一个应用程序
开始使用 Avalonia 的最佳方式是用项目模板创建一个应用程序

要安装 Avalonia 模板,请运行以下命令:
要安装 [Avalonia 模板](https://github.com/AvaloniaUI/avalonia-dotnet-templates),请运行以下命令:

```bash
dotnet new install Avalonia.Templates
Expand All @@ -17,10 +21,10 @@ dotnet new install Avalonia.Templates
对于 .NET 6.0 及更早版本,请将 `install` 替换为 `--install`
:::

要列出已安装的模板,请运行以下命令:
要列出已安装的模板,请运行

```bash
dotnet new list
dotnet new list
```

您应该可以看到已安装的 Avalonia 模板:
Expand All @@ -36,4 +40,49 @@ Avalonia Styles avalonia.styles
Avalonia TemplatedControl avalonia.templatedcontrol [C#],F# Desktop/Xaml/Avalonia/Windows/Linux/macOS
Avalonia UserControl avalonia.usercontrol [C#],F# Desktop/Xaml/Avalonia/Windows/Linux/macOS
Avalonia Window avalonia.window [C#],F# Desktop/Xaml/Avalonia/Windows/Linux/macOS
```
```

## 创建新的应用程序

项目模板安装完成后,您可以通过命令行运行以下命令创建一个新的 Avalonia UI 应用程序:

```bash
dotnet new avalonia.app -o MyApp
```

这会创建一个名为 `MyApp` 的新文件夹,其中包含您的应用程序文件。要运行应用程序,请导航到 `MyApp` 文件夹并运行:

```bash
cd MyApp
dotnet run
```

项目模板还允许从您的 IDE 创建项目。

## 安装故障排除

### 确保已安装 .NET SDK

确保您已经安装了 .NET SDK。您可以运行以下命令检查已安装的 .NET SDK 版本:

```bash
dotnet --version
```

如果 `dotnet` 不是识别的程序,请确保您已经安装了 IDE。接下来,确保 `dotnet` 已关联到终端。在 Windows 上,这涉及检查环境变量:在命令提示符中运行 `echo %PATH%` 或在 PowerShell 中运行 `echo $Env:PATH`

### 确保 NuGet 源配置正确

如果在安装项目模板时收到错误,提示 `Avalonia.Templates` 包无法找到,请确保 NuGet 已正确配置为 .NET 的标准全局包源。您可以运行以下命令检查 NuGet 源:

```bash
dotnet nuget list source
```

如果未列出此源,请运行以下命令添加 NuGet 源:

```bash
dotnet nuget add source https://api.nuget.org/v3/index.json -n nuget.org
```

如果NuGet已列出,但是包安装仍然失败,请考虑网络连接或防火墙问题。
Loading

0 comments on commit 9d26a46

Please sign in to comment.