欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

第十八章:MVVM(八)

程序员文章站 2023-12-23 19:05:27
...

简单的方法执行
让我们看一个简单的例子。一个名为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> 

这是几次按下一个按钮或另一个按钮后的样子:
第十八章:MVVM(八)
再一次,当需要更改视图时,就会发现将用户界面与底层业务逻辑分离的智慧。 例如,假设您要使用带有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或甚至重命名事件处理程序以使其应用于点击而不是按钮的情况下,程序的工作方式相同,但外观不同:
第十八章:MVVM(八)

上一篇:

下一篇: