博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
第二十章:异步和文件I/O.(二十一)
阅读量:6848 次
发布时间:2019-06-26

本文共 10262 字,大约阅读时间需要 34 分钟。

因此,MandelbrotViewModel类具有许多属性,但如果您不考虑用户界面,则可能与您定义的属性不同。 CurrentCenter属性是程序当前显示的图像中心的复数,CurrentMagnification也适用于该图像。 但TargetMagnification绑定到Stepper的当前设置,它将应用于下一个计算的图像。 RealOffset和ImaginaryOffset属性绑定到两个Slider元素,范围从0到1.从CurrentCenter,CurrentMagnification,RealOffset和ImaginaryOffset属性,ViewModel可以计算TargetCenter属性。 这是下一个计算图像的中心。 如您所见,该TargetCenter属性用于显示两个滑块下方的复数:

namespace MandelbrotXF{    class MandelbrotViewModel : ViewModelBase    {        // Set via constructor arguments.        readonly double baseWidth;        readonly double baseHeight;        // Backing fields for properties.        Complex currentCenter, targetCenter;        int pixelWidth, pixelHeight;        double currentMagnification, targetMagnification;        int iterations;        double realOffset, imaginaryOffset;        bool isBusy;        double progress;        BitmapInfo bitmapInfo;        public MandelbrotViewModel(double baseWidth, double baseHeight)        {            this.baseWidth = baseWidth;            this.baseHeight = baseHeight;            // Create MandelbrotModel object.            MandelbrotModel model = new MandelbrotModel();            // Progress reporter            Progress
progressReporter = new Progress
((double progress) => { Progress = progress; }); CancellationTokenSource cancelTokenSource = null; // Define CalculateCommand and CancelCommand. CalculateCommand = new Command( execute: async () => { // Disable this button and enable Cancel button. IsBusy = true; ((Command)CalculateCommand).ChangeCanExecute(); ((Command)CancelCommand).ChangeCanExecute(); // Create CancellationToken. cancelTokenSource = new CancellationTokenSource(); CancellationToken cancelToken = cancelTokenSource.Token; try { // Perform the calculation. BitmapInfo = await model.CalculateAsync(TargetCenter, baseWidth / TargetMagnification, baseHeight / TargetMagnification, PixelWidth, PixelHeight, Iterations, progressReporter, cancelToken); // Processing only for a successful completion. CurrentCenter = TargetCenter; CurrentMagnification = TargetMagnification; RealOffset = 0.5; ImaginaryOffset = 0.5; } catch (OperationCanceledException) { // Operation cancelled! } catch { // Another type of exception? This should not occur. } // Processing regardless of success or cancellation. Progress = 0; IsBusy = false; // Disable Cancel button and enable this button. ((Command)CalculateCommand).ChangeCanExecute(); ((Command)CancelCommand).ChangeCanExecute(); }, canExecute: () => { return !IsBusy; }); CancelCommand = new Command( execute: () => { cancelTokenSource.Cancel(); }, canExecute: () => { return IsBusy; }); } public int PixelWidth { set { SetProperty(ref pixelWidth, value); } get { return pixelWidth; } } public int PixelHeight { set { SetProperty(ref pixelHeight, value); } get { return pixelHeight; } } public Complex CurrentCenter { set { if (SetProperty(ref currentCenter, value)) CalculateTargetCenter(); } get { return currentCenter; } } public Complex TargetCenter { private set { SetProperty(ref targetCenter, value); } get { return targetCenter; } } public double CurrentMagnification { set { SetProperty(ref currentMagnification, value); } get { return currentMagnification; } } public double TargetMagnification { set { SetProperty(ref targetMagnification, value); } get { return targetMagnification; } } public int Iterations { set { SetProperty(ref iterations, value); } get { return iterations; } } // These two properties range from 0 to 1. // They indicate a new center relative to the // current width and height, which is the baseWidth // and baseHeight divided by CurrentMagnification. public double RealOffset { set { if (SetProperty(ref realOffset, value)) CalculateTargetCenter(); } get { return realOffset; } } public double ImaginaryOffset { set { if (SetProperty(ref imaginaryOffset, value)) CalculateTargetCenter(); } get { return imaginaryOffset; } } void CalculateTargetCenter() { double width = baseWidth / CurrentMagnification; double height = baseHeight / CurrentMagnification; TargetCenter = new Complex(CurrentCenter.Real + (RealOffset - 0.5) * width, CurrentCenter.Imaginary + (ImaginaryOffset - 0.5) * height); } public bool IsBusy { private set { SetProperty(ref isBusy, value); } get { return isBusy; } } public double Progress { private set { SetProperty(ref progress, value); } get { return progress; } } public BitmapInfo BitmapInfo { private set { SetProperty(ref bitmapInfo, value); } get { return bitmapInfo; } } public ICommand CalculateCommand { private set; get; } public ICommand CancelCommand { private set; get; } }}

MandelbrotViewModel还为Calculate和Cancel按钮,Progress属性和IsBusy属性定义了ICommand类型的两个属性。 正如您将看到的,IsBusy属性用于显示这两个按钮中的一个并隐藏另一个按钮,并在计算过程中禁用其余的用户界面。 这两个ICommand属性是在类的构造函数中使用lambda函数实现的。

XAML文件中的数据绑定到MandelbrotViewModel中的属性需要Xamarin.FormsBook.Toolkit库中的两个新绑定转换器。 第一个简单地否定了bool值:

namespace Xamarin.FormsBook.Toolkit{    public class BooleanNegationConverter : IValueConverter    {        public object Convert(object value, Type targetType,                               object parameter, CultureInfo culture)        {            return !(bool)value;        }        public object ConvertBack(object value, Type targetType,                                   object parameter, CultureInfo culture)        {            return !(bool)value;        }    }}

它与ViewModel的IsBusy属性一起使用。 当IsBusy为true时,需要将几个元素的IsEnabled属性和Go按钮的IsVisible属性设置为false。

两个Stepper元素实际上控制ViewModel中值的指数。 例如,Stepper值为8,对应于Iterations或TargetMagnification值256.该转换需要base-2对数转换器:

namespace Xamarin.FormsBook.Toolkit{    public class BaseTwoLogConverter : IValueConverter    {        public object Convert(object value, Type targetType,                               object parameter, CultureInfo culture)        {            if (value is int)            {                return Math.Log((int)value) / Math.Log(2);            }            return Math.Log((double)value) / Math.Log(2);        }        public object ConvertBack(object value, Type targetType,                                   object parameter, CultureInfo culture)        {            double returnValue = Math.Pow(2, (double)value);            if (targetType == typeof(int))            {                return (int) returnValue;            }            return returnValue;        }    }}

这是XAML文件,绑定到ViewModel的Progress,RealOffset,ImaginaryOffset,TargetCenter,TargetMagnification,Iterations,IsBusy,CalculateCommand和CancelCommand属性:

此XAML文件仅安装三个事件处理程序,它们都是SizeChanged处理程序。

转载地址:http://ljlul.baihongyu.com/

你可能感兴趣的文章