简单的方法执行
让我们看一个简单的例子。一个名为PowersOfThree的程序允许您使用两个按钮来探索3的各种幂。一个按钮增加指数,另一个按钮减少指数。
PowersViewModel类派生自Xamarin.FormsBook.Toolkit库中的ViewModelBase类,但ViewModel本身位于PowersOfThree应用程序项目中。它不限于3的幂,但构造函数需要一个参数,该类用作功率计算的基值,并作为BaseValue属性公开。因为此属性具有私有集访问器,并且在构造函数结束后不会更改,所以该属性不会触发PropertyChanged事件。
另外两个名为Exponent和Power的属性会触发PropertyChanged事件,但这两个属性也有私有集访问器。 Exponent属性仅从外部按钮单击增加和减少。
为了实现对Button抽头的响应,PowersViewModel类定义了两个类型为ICommand的属性,名为IncreaseExponentCommand和DecreaseExponentCommand。同样,这两个属性都有私有集访问器。如您所见,构造函数通过实例化紧跟构造函数后引用很少私有方法的Command对象来设置这两个属性。调用Command的Execute方法时会调用这两个小方法。 ViewModel使用Command类而不是Command ,因为程序没有使用Execute方法的任何参数:
class PowersViewModel : ViewModelBase
{
double exponent, power;
public PowersViewModel(double baseValue)
{
// Initialize properties.
BaseValue = baseValue;
Exponent = 0;
// Initialize ICommand properties.
IncreaseExponentCommand = new Command(ExecuteIncreaseExponent);
DecreaseExponentCommand = new Command(ExecuteDecreaseExponent);
}
void ExecuteIncreaseExponent()
{
Exponent += 1;
}
void ExecuteDecreaseExponent()
{
Exponent -= 1;
}
public double BaseValue { private set; get; }
public double Exponent
{
private set
{
if (SetProperty(ref exponent, value))
{
Power = Math.Pow(BaseValue, exponent);
}
}
get
{
return exponent;
}
}
public double Power
{
private set { SetProperty(ref power, value); }
get { return power; }
}
public ICommand IncreaseExponentCommand { private set; get; }
public ICommand DecreaseExponentCommand { private set; get; }
}
ExecuteIncreaseExponent和ExecuteDecreaseExponent方法都会更改Exponent属性(触发PropertyChanged事件),Exponent属性重新计算Power属性,该属性也会触发PropertyChanged事件。
通常,ViewModel将通过将lambda函数传递给Command构造函数来实例化其Command对象。 这种方法允许在ViewModel构造函数中定义这些方法,如下所示:
IncreaseExponentCommand = new Command(() =>
{
Exponent += 1;
});
DecreaseExponentCommand = new Command(() =>
{
Exponent -= 1;
});
PowersOfThreePage XAML文件将三个Label元素的Text属性绑定到PowersViewModel类的BaseValue,Exponent和Power属性,并将两个Button元素的Command属性绑定到ViewModel的IncreaseExponentCommand和DecreaseExponentCommand属性。
注意如何将参数3传递给PowersViewModel的构造函数,因为它在Resources字典中实例化。 将参数传递给ViewModel构造函数是存在x:Arguments标记的主要原因:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:PowersOfThree"
x:Class="PowersOfThree.PowersOfThreePage">
<ContentPage.Resources>
<ResourceDictionary>
<local:PowersViewModel x:Key="viewModel">
<x:Arguments>
<x:Double>3</x:Double>
</x:Arguments>
</local:PowersViewModel>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout BindingContext="{StaticResource viewModel}">
<StackLayout Orientation="Horizontal"
Spacing="0"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand">
<Label FontSize="Large"
Text="{Binding BaseValue, StringFormat='{0}'}" />
<Label FontSize="Small"
Text="{Binding Exponent, StringFormat='{0}'}" />
<Label FontSize="Large"
Text="{Binding Power, StringFormat=' = {0}'}" />
</StackLayout>
<StackLayout Orientation="Horizontal"
VerticalOptions="CenterAndExpand">
<Button Text="Increase"
Command="{Binding IncreaseExponentCommand}"
HorizontalOptions="CenterAndExpand" />
<Button Text="Decrease"
Command="{Binding DecreaseExponentCommand}"
HorizontalOptions="CenterAndExpand" />
</StackLayout>
</StackLayout>
</ContentPage>
这是几次按下一个按钮或另一个按钮后的样子:
再一次,当需要更改视图时,就会发现将用户界面与底层业务逻辑分离的智慧。 例如,假设您要使用带有TapGestureRecognizer的元素替换按钮。 幸运的是,TapGestureRecognizer有一个Command属性:
<StackLayout Orientation="Horizontal"
VerticalOptions="CenterAndExpand">
<Frame OutlineColor="Accent"
BackgroundColor="Transparent"
Padding="20, 40"
HorizontalOptions="CenterAndExpand">
<Frame.GestureRecognizers>
<TapGestureRecognizer Command="{Binding IncreaseExponentCommand}" />
</Frame.GestureRecognizers>
<Label Text="Increase"
FontSize="Large" />
</Frame>
<Frame OutlineColor="Accent"
BackgroundColor="Transparent"
Padding="20, 40"
HorizontalOptions="CenterAndExpand">
<Frame.GestureRecognizers>
<TapGestureRecognizer Command="{Binding DecreaseExponentCommand}" />
</Frame.GestureRecognizers>
<Label Text="Decrease"
FontSize="Large" />
</Frame>
</StackLayout>
在没有触摸ViewModel或甚至重命名事件处理程序以使其应用于点击而不是按钮的情况下,程序的工作方式相同,但外观不同: