Uno Platform 偵查報告 -- 基本資料與命令繫結

資料和命令繫結是各種 xaml 平台裡非常重要的一項特色,這場偵查就寫個體脂肪計算器測試看看。

Uno.UI version: 1.40.0 穩定版
偵查對象:Data and Command Binding

資料和命令繫結向來是使用 xaml 的各式平台的重頭大戲,這一篇我們同時來測試簡單的資料和命令繫結。程式本身內容很簡單,就是個 BMI 的計算器而已。

簡易的命令通用類別,RelayCommand class
    public class RelayCommand : ICommand
    {
        private readonly Action<object> _executeHandler;
        private readonly Func<object, bool> _canExecuteHandler;

        public event EventHandler CanExecuteChanged;
        public RelayCommand(Action<object> executeHandler, Func<object, bool> canExecuteHandler)
        {
            _executeHandler = executeHandler ?? throw new ArgumentNullException("execute handler can not be null");
            _canExecuteHandler = canExecuteHandler ?? throw new ArgumentNullException("canExecute handler can not be null");
        }

        public RelayCommand(Action<object> execute) : this(execute, (x) => true)
        { }

        public bool CanExecute(object parameter)
        {
            return _canExecuteHandler(parameter);
        }

        public void Execute(object parameter)
        {
            _executeHandler(parameter);
        }
     
    }
 資料類別 Person class
  public class Person : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private double _height;
        public double Height
        {
            get { return _height; }
            set
            {
                if (value != _height )
                {
                    _height = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Height)));
                }
            }
        }

        private double _weight;
        public double Weight
        {
            get { return _weight; }
            set
            {
                if (value != _weight)
                {
                    _weight = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Weight)));
                }
            }
        }

        private double _result;
        public double Result
        {
            get { return _result; }
            set
            {
                if (value != _result)
                {
                    _result = value;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Result)));
                }
            }
        }

        private ICommand _clickCommand;
        public ICommand ClickCommand
        {
            get
            {
                if (_clickCommand == null)
                {
                    _clickCommand = new RelayCommand((x) =>
                   {
                       Result = Weight / Math.Pow(Height, 2);                        
                   });
                }
                return _clickCommand;
            }
        }
    }
XAML Code
<Page  
    x:Class="UnoBMIApp.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UnoBMIApp"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:vm="using:UnoBMIApp.ViewModels"
    mc:Ignorable="d">
    <Page.DataContext>
        <vm:Person/>
    </Page.DataContext>
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Margin="6,32,6,6">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <TextBlock Text="Height (M)" Grid.Row="0" Grid.Column="0" Margin="6"/>
        <TextBox Text="{Binding Height, Mode=TwoWay}" Grid.Row="0" Grid.Column="1" Margin="6"/>
        <TextBlock Text="Weight (Kg)" Grid.Row="1" Grid.Column="0" Margin="6"/>
        <TextBox Text="{Binding Weight, Mode=TwoWay}" Grid.Row="1" Grid.Column="1" Margin="6"/>
        <Button Content="Compute BMI" Command="{Binding ClickCommand}" Grid.Row="2" Grid.ColumnSpan="2" Margin="6" HorizontalAlignment="Stretch"/>
        <TextBlock Text="{Binding Result, Mode=OneWay}" Grid.Row="3" Grid.ColumnSpan="2" Margin="6" HorizontalAlignment="Stretch"/>
    </Grid>
</Page>

就這個範例而言,不論 Android 或 iOS 都可以正常運作。這表示 Uno Platform 基本上在簡單資料與命令繫結上是正常的,即便 Two way binding 也是如預期的反應畫面的資料變更到 view model 中。

這篇文的範例在 https://github.com/billchungiii/UnoBMIApp