Skip to content

Commit

Permalink
translate bindablebase
Browse files Browse the repository at this point in the history
  • Loading branch information
CoreyLyn committed Apr 30, 2024
1 parent a3a4d0f commit 30593c1
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 31 deletions.
11 changes: 6 additions & 5 deletions docs/_sidebar.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,23 @@
- [附录](dependency-injection/appendix.md)
- 对话服务(Dialog Service)
- [对话服务](dialogs/index.md)
- [IDialogAware ViewModels](dialogs/dialog-aware.md)
- [IDialogWindow(WPF & Uno Platform](dialogs/dialog-window.md)
- [IDialogAware 视图模型](dialogs/dialog-aware.md)
- [IDialogWindow(WPF & Uno 平台](dialogs/dialog-window.md)
- [事件聚合器(Event Aggregator)](event-aggregator.md)
- Mvvm
- [绑定](mvvm/bindablebase.md)
- [ViewModelLocator](mvvm/viewmodel-locator.md)
- [BindableBase](mvvm/bindablebase.md)
- [ViewModel 定位器(ViewModelLocator](mvvm/viewmodel-locator.md)
- 模块化(Modularity)
- [开始使用](modularity/index.md)
- [模块目录](modularity/module-catalog.md)
- [模块初始化](modularity/module-initialization.md)
- 导航(Navigation)
- [INavigationParameters](navigation/navigation-parameters.md)
- [Page Navigation](navigation/page-navigation.md)
- [页面导航](navigation/page-navigation.md)
- 区域(Regions)
- [开始使用](navigation/regions/index.md)
- 平台(Platforms)
- Wpf
- [介绍](platforms/wpf/introduction.md)
- 插件(Plugins)
- 基本会话
32 changes: 16 additions & 16 deletions docs/commands/commanding.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@

当命令与视图交互时,用户可以通过许多不同的方式直观地表示和调用命令。在大多数情况下,它们会因单击鼠标而调用,但也可以通过快捷键按下、触摸手势或任何其他输入事件来调用。视图中的控件是绑定到 ViewModel 命令的数据,以便用户可以使用控件定义的任何输入事件或手势来调用它们。视图中的 UI 控件与命令之间的交互可以是双向的。在这种情况下,可以在用户与 UI 交互时调用该命令,并且可以在启用或禁用基础命令时自动启用或禁用 UI。

ViewModel 可以将命令实现为命令对象(实现接口的 ICommand 对象)。视图与命令的交互可以通过声明方式定义,而无需在视图的代码隐藏文件中编写复杂的事件处理代码。例如,某些控件本身支持命令,并提供一个 Command 属性,该属性可以绑定到 ViewModel 提供的 ICommand 对象的数据。在其他情况下,命令行为可用于将控件与 ViewModel 提供的命令方法或命令对象相关联。
ViewModel 可以将命令实现为命令对象(实现接口的 `ICommand` 对象)。视图与命令的交互可以通过声明方式定义,而无需在视图的代码隐藏文件中编写复杂的事件处理代码。例如,某些控件本身支持命令,并提供一个 `Command` 属性,该属性可以绑定到 ViewModel 提供的 `ICommand` 对象的数据。在其他情况下,命令行为可用于将控件与 ViewModel 提供的命令方法或命令对象相关联。

实现 ICommand 接口很简单。Prism 提供了此接口的 DelegateCommand 实现,您可以在应用程序中轻松使用。
实现 `ICommand` 接口很简单。Prism 提供了此接口的 `DelegateCommand` 实现,您可以在应用程序中轻松使用。

?> DelegateCommand 可以在 Prism.Core NuGet 包中的 Prism.Commands 命名空间中找到。
?> `DelegateCommand` 可以在 Prism.Core NuGet 包中的 Prism.Commands 命名空间中找到。

Prism DelegateCommand 类封装了两个委托,每个委托都引用在 ViewModel 类中实现的方法。它通过调用这些委托来实现 ICommand 接口 Execute 的和 CanExecute 方法。在 DelegateCommand 类构造函数中指定 ViewModel 方法的委托。例如,下面的代码示例演示如何通过指定 OnSubmit 和 CanSubmit ViewModel 方法的委托来构造表示 Submit 命令的 DelegateCommand 实例。然后,该命令通过只读属性向视图公开,该属性返回对 DelegateCommand。
Prism `DelegateCommand` 类封装了两个委托,每个委托都引用在 ViewModel 类中实现的方法。它通过调用这些委托来实现 `ICommand` 接口 `Execute` 的和 `CanExecute` 方法。在 `DelegateCommand` 类构造函数中指定 ViewModel 方法的委托。例如,下面的代码示例演示如何通过指定 OnSubmit 和 CanSubmit ViewModel 方法的委托来构造表示 Submit 命令的 `DelegateCommand` 实例。然后,该命令通过只读属性向视图公开,该属性返回对 `DelegateCommand`

```cs
public class ArticleViewModel
Expand All @@ -34,9 +34,9 @@ public class ArticleViewModel
}
```

在 DelegateCommand 对象上调用 Execute 方法时,它只是通过在构造函数中指定的委托将调用转发给 ViewModel 类中的方法。同样,调用该 CanExecute 方法时,将调用 ViewModel 类中的相应方法。构造函数中方法的 CanExecute 委托是可选的。如果未指定委托, DelegateCommand 则始终返回 true CanExecute
`DelegateCommand` 对象上调用 Execute 方法时,它只是通过在构造函数中指定的委托将调用转发给 ViewModel 类中的方法。同样,调用该 `CanExecute` 方法时,将调用 ViewModel 类中的相应方法。构造函数中方法的 `CanExecute` 委托是可选的。如果未指定委托, `DelegateCommand` 则始终 `CanExecute` 返回 `true`

该 DelegateCommand 类是泛型类型。type 参数指定传递给 Execute and CanExecute 方法的命令参数的类型。在前面的示例中,命令参数的类型 object 为 。Prism 还提供了该 DelegateCommand 类的非泛型版本,供在不需要命令参数时使用,其定义如下:
`DelegateCommand` 类是泛型类型。type 参数指定传递给 `Execute``CanExecute` 方法的命令参数的类型。在前面的示例中,命令参数的类型 `object` 为 。Prism 还提供了该 `DelegateCommand` 类的非泛型版本,供在不需要命令参数时使用,其定义如下:

```cs
public class ArticleViewModel
Expand All @@ -60,20 +60,20 @@ public class ArticleViewModel
}
```

?>故意 DelegateCommand 阻止使用值类型(int、double、bool 等)。因为 ICommand 需要 object ,所以在命令绑定的 XAML 初始化期间调用 时,具有 的 T 值类型会导致意外行为 CanExecute(null) 。使用 default(T) 被考虑并被拒绝作为解决方案,因为实现者无法区分有效值和默认值。如果希望使用值类型作为参数,则必须使用 DelegateCommand<Nullable<int>> 或速记 ? 语法 ( DelegateCommand<int?> ) 使其可为 null。
?> `DelegateCommand` 故意阻止使用值类型(int、double、bool 等)。因为 `ICommand` 需要 `object` ,所以在命令绑定的 XAML 初始化期间调用 时,具有 的 `T` 值类型会导致意外行为 `CanExecute(null)` 。使用 `default(T)` 被考虑并被拒绝作为解决方案,因为实现者无法区分有效值和默认值。如果希望使用值类型作为参数,则必须使用 `DelegateCommand<Nullable<int>>` 或速记 `?` 语法 ( `DelegateCommand<int?>` ) 使其可为 null。

# 从视图调用 DelegateCommands
视图中的控件可以通过多种方式与 ViewModel 提供的命令对象相关联。某些 WPF、Xamarin.Forms 和 UWP 控件可以通过 Command 该属性轻松数据绑定到命令对象。
视图中的控件可以通过多种方式与 ViewModel 提供的命令对象相关联。某些 WPF、Xamarin.Forms 和 UWP 控件可以通过 `Command` 该属性轻松数据绑定到命令对象。
```
<Button Command="{Binding SubmitCommand}" CommandParameter="OrderId"/>
```
还可以选择使用该 CommandParameter 属性定义命令参数。预期参数的类型在 DelegateCommand<T> 泛型声明中指定。当用户与该控件交互时,该控件将自动调用该命令,并且命令参数(如果提供)将作为参数传递给该命令 Execute 的方法。在前面的示例中,单击按钮时将自动调用。 SubmitCommand 此外,如果指定了 CanExecute 委托,则该按钮将在 CanExecute 返回 false 时自动禁用,如果返回 true ,则启用该按钮。
还可以选择使用该 `CommandParameter` 属性定义命令参数。预期参数的类型在 `DelegateCommand<T>` 泛型声明中指定。当用户与该控件交互时,该控件将自动调用该命令,并且命令参数(如果提供)将作为参数传递给该命令 `Execute` 的方法。在前面的示例中,单击按钮时将自动调用。 `SubmitCommand` 此外,如果指定了 `CanExecute` 委托,则该按钮将在 `CanExecute` 返回 `false` 时自动禁用,如果返回 `true` ,则启用该按钮。

# 引发变更通知
ViewModel 通常需要指示命令 CanExecute 状态的更改,以便 UI 中绑定到命令的任何控件都将更新其启用状态,以反映绑定命令的可用性。提供了 DelegateCommand 几种将这些通知发送到 UI 的方法。
ViewModel 通常需要指示命令 `CanExecute` 状态的更改,以便 UI 中绑定到命令的任何控件都将更新其启用状态,以反映绑定命令的可用性。提供了 `DelegateCommand` 几种将这些通知发送到 UI 的方法。

# RaiseCanExecuteChanged
每当需要手动更新绑定的 UI 元素的状态时,请使用该 RaiseCanExecuteChanged 方法。例如,当 IsEnabled 属性值发生更改时,我们将调用 RaiseCanExecuteChanged 属性的 setter 以通知 UI 状态更改。
每当需要手动更新绑定的 UI 元素的状态时,请使用该 `RaiseCanExecuteChanged` 方法。例如,当 `IsEnabled` 属性值发生更改时,我们将调用 `RaiseCanExecuteChanged` 属性的 setter 以通知 UI 状态更改。
```cs
private bool _isEnabled;
public bool IsEnabled
Expand All @@ -87,7 +87,7 @@ public bool IsEnabled
}
```
# ObservesProperty
如果命令应在属性值更改时发送通知,则可以使用该 ObservesProperty 方法。使用该 ObservesProperty 方法时,每当提供的属性的值发生更改时, DelegateCommand 都会自动调用 RaiseCanExecuteChanged 以通知 UI 状态更改。
如果命令应在属性值更改时发送通知,则可以使用该 `ObservesProperty` 方法。使用该 `ObservesProperty` 方法时,每当提供的属性的值发生更改时, `DelegateCommand` 都会自动调用 `RaiseCanExecuteChanged` 以通知 UI 状态更改。
```cs
public class ArticleViewModel : BindableBase
{
Expand Down Expand Up @@ -116,10 +116,10 @@ public class ArticleViewModel : BindableBase
}
}
```
?>使用该 ObservesProperty 方法时,可以链式注册多个属性以进行观察。示例: ObservesProperty(() => IsEnabled).ObservesProperty(() => CanSave) .
?>使用该 `ObservesProperty` 方法时,可以链式注册多个属性以进行观察。示例: `ObservesProperty(() => IsEnabled).ObservesProperty(() => CanSave)` .

# ObservesCanExecute
如果你的 CanExecute 是简单 Boolean 属性的结果,则可以省去声明 CanExecute 委托的需要,而是使用该 ObservesCanExecute 方法。 ObservesCanExecute 不仅会在注册的属性值更改时向 UI 发送通知,而且还会使用与实际 CanExecute 委托相同的属性。
如果你的 `CanExecute` 是简单 Boolean 属性的结果,则可以省去声明 `CanExecute` 委托的需要,而是使用该 `ObservesCanExecute` 方法。 `ObservesCanExecute` 不仅会在注册的属性值更改时向 UI 发送通知,而且还会使用与实际 `CanExecute` 委托相同的属性。
```cs
public class ArticleViewModel : BindableBase
{
Expand All @@ -144,10 +144,10 @@ public class ArticleViewModel : BindableBase
}
```

!>不要尝试链式寄存器 ObservesCanExecute 方法。只能观察到 CanExcute 委托的一个属性。
!>不要尝试链式寄存器 `ObservesCanExecute` 方法。只能观察到 `CanExcute` 委托的一个属性。

# 实现基于任务的 DelegateCommand
在当今的 async / await 世界中,在委托内部 Execute 调用异步方法是一个非常常见的要求。每个人的第一反应是他们需要一个 AsyncCommand ,但这种假设是错误的。 ICommand 从本质上讲, Execute 它是同步的,并且应将 AND CanExecute 委托视为事件。这意味着 async void 这是用于命令的完全有效的语法。有两种方法可以将 async 方法与 DelegateCommand .
在当今的 `async` / `await`,在委托内部 `Execute` 调用异步方法是一个非常常见的要求。每个人的第一反应是他们需要一个 `AsyncCommand` ,但这种假设是错误的。 `ICommand` 从本质上讲它是同步的,并且应将 `Execute``CanExecute` 委托视为事件。这意味着 `async void` 这是用于命令的完全有效的语法。有两种方法可以将 async 方法与 `DelegateCommand` .

方式 1:
```cs
Expand Down
2 changes: 1 addition & 1 deletion docs/commands/composite-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The `CompositeCommand` class maintains a list of child commands (`DelegateComman
> [!NOTE]
> `CompositeCommand` can be found in the Prism.Commands namespace which is located in the Prism.Core NuGet package.
> [!Video https://www.youtube.com/embed/kssprOqdfME]
<iframe height="510" src="https://www.youtube.com/embed/kssprOqdfME">
## Creating a Composite Command
Expand Down
17 changes: 8 additions & 9 deletions docs/mvvm/bindablebase.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# BindableBase

Like you would expect from any MVVM Library, Prism provides a base class implementing `INotifyPropertyChanged`. While it's important to understand how to use it, it's also important to note that features within Prism such as responding to lifecycle events, navigation, etc... are all interface driven. This means that while Prism provides the `BindableBase` as a base implementation of `INotifyPropertyChanged` to better assist you, Prism also has no strict requirement on you to use it. This means that you may use any base class you want for your ViewModels including no base class at all (though that isn't generally recommended).
就像您对任何 MVVM 库的期望一样,Prism 提供了一个基类实现 `INotifyPropertyChanged` 。虽然了解如何使用它很重要,但同样重要的是要注意 Prism 中的功能,例如响应生命周期事件、导航等......都是接口驱动的。这意味着,虽然 Prism 提供了 `BindableBase` 作为基本实现 `INotifyPropertyChanged` 以更好地帮助您,但 Prism 也没有严格要求您使用它。这意味着您可以为 ViewModel 使用所需的任何基类,但根本不包含基类(尽管通常不建议这样做)。

## Creating Properties
## 创建属性

Properties used within a class inheriting from `BindableBase` which must notify the UI of changes should make use of the `SetProperty` method to set the changes and should have both a public property as well as a private backing field. The result is something like this:
在继承的类 `BindableBase` 中使用的属性必须通知 UI 更改,应使用 `SetProperty` 该方法来设置更改,并且应同时具有公共属性和私有支持字段。结果是这样的:

```cs
public class ViewAViewModel : BindableBase
Expand All @@ -18,9 +18,9 @@ public class ViewAViewModel : BindableBase
}
```

### Why Use SetProperty
### 为什么使用 SetProperty

You may be wondering, why use `SetProperty`? After all can't you just call RaisePropertyChanged yourself? The short answer is that you can. However this is generally not advisable because you will lose the built in EqualityComparer which helps to ensure that if the setter is called multiple times with the same value `INotifyPropertyChanged` will only trigger the `PropertyChanged` event the first time it changes.
您可能想知道,为什么要使用 `SetProperty` ?毕竟,你不能自己调用RaisePropertyChanged吗?简短的回答是你可以。但是,这通常是不可取的,因为您将丢失内置的 EqualityComparer,这有助于确保如果多次调用具有相同值 `INotifyPropertyChanged` 的 setter,则仅在事件第一次更改时触发 `PropertyChanged` 事件。

```cs
public class ViewAViewModel : BindableBase
Expand All @@ -39,12 +39,11 @@ public class ViewAViewModel : BindableBase
}
```

> [!TIP]
> As we have reviewed code in production, we have commonly run into code like the above sample. This code is fundamentally flawed, overly verbose and will result in unnecessary PropertyChanged events being raised for the property. You should always base your code flow around SetProperty.
?> 当我们在生产环境中查看代码时,我们通常会遇到类似上述示例的代码。此代码从根本上存在缺陷,过于冗长,将导致为属性引发不必要的 PropertyChanged 事件。应始终以 SetProperty 为基础编写代码流。

### Executing a Delegate on PropertyChanges
### PropertyChanges 上执行委托

Sometimes you may want to provide a callback when the property changes. One such example could be that you are implementing `IActiveAware` and you want to provide a method that will only execute when IsActive is true and another when it is false.
有时,您可能希望在属性更改时提供回调。一个这样的示例可能是您正在实现 `IActiveAware` ,并且您希望提供一个仅在 IsActive true 时执行的方法,并在 IsActive 为 false 时执行另一个方法。

```cs
public abstract class ViewModelBase : BindableBase, IActiveAware
Expand Down

0 comments on commit 30593c1

Please sign in to comment.