入口属性和活动
除了从InputView继承Keyboard属性之外,Entry还定义了另外四个属性,其中只有一个属性在上一个程序中看到:
- Text - 条目中显示的字符串
- TextColor - 颜色值
- IsPassword - 一种布尔值,可以在输入字符后立即屏蔽字符
- Placeholder - 条目中显示的浅色文本,但在用户开始输入后立即消失。
通常,程序通过访问Text属性来获取用户键入的内容,但程序也可以初始化Text属性。 也许程序希望建议一些文本输入。
Entry还定义了两个事件:
- TextChanged
- Completed
Text属性的每次更改都会触发TextChanged事件,这通常对应于每次击键(shift和一些特殊键除外)。 程序可以监视此事件以执行有效性检查。 例如,您可以检查有效数字或有效电子邮件地址以启用“计算”或“发送”按钮。
当用户按下键盘上的特定键以指示文本已完成时,将触发Completed事件。 此密钥是特定于平台的:
- iOS:密钥标记为return,不在电话或数字键盘上。
- Android:键是键盘右下角的绿色复选标记。
- WindowsPhone:键是大多数键盘上的输入(或返回)符号(?),但在Url键盘上是一个符号(→)。 电话和数字键板上没有这样的键。
在iOS和Android上,完成的键除了生成Completed事件外还会解除键盘。 在Windows 10 Mobile上它没有。
Android和Windows用户也可以使用纵向屏幕左下角的手机“后退”按钮来关闭键盘。 这会导致Entry失去输入焦点,但不会导致Completed事件触发。
让我们编写一个名为QuadraticEquations的程序来求解二次方程,它是以下形式的方程式:
axx + bx + c = 0
对于任何三个常数a,b和c,程序使用二次方程求解x:
x = (-b + sqrt(b*b-4ac)/2a) 或者
x = (-b - sqrt(b*b-4ac)/2a)
在三个Entry视图中输入a,b和c,然后按一个标记为Solve for x的按钮。
这是XAML文件。 不幸的是,数字键盘不适合这个程序,因为在所有三个平台上它都不允许输入负数。 因此,没有指定特定的键盘:
点击(此处)折叠或打开
- <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
- xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
- x:Class="QuadaticEquations.QuadraticEquationsPage">
- <ContentPage.Resources>
- <ResourceDictionary>
- <Style TargetType="Label">
- <Setter Property="FontSize" Value="Medium" />
- <Setter Property="VerticalOptions" Value="Center" />
- </Style>
- <Style TargetType="Entry">
- <Setter Property="WidthRequest" Value="180" />
- </Style>
- </ResourceDictionary>
- </ContentPage.Resources>
- <StackLayout>
- <!-- Entry section -->
- <StackLayout Padding="20, 0, 0, 0"
- VerticalOptions="CenterAndExpand"
- HorizontalOptions="Center">
- <StackLayout Orientation="Horizontal">
- <Entry x:Name="entryA"
- TextChanged="OnEntryTextChanged"
- Completed="OnEntryCompleted" />
- <Label Text=" x² +" />
- </StackLayout>
- <StackLayout Orientation="Horizontal">
- <Entry x:Name="entryB"
- TextChanged="OnEntryTextChanged"
- Completed="OnEntryCompleted" />
- <Label Text=" x +" />
- </StackLayout>
- <StackLayout Orientation="Horizontal">
- <Entry x:Name="entryC"
- TextChanged="OnEntryTextChanged"
- Completed="OnEntryCompleted" />
- <Label Text=" = 0" />
- </StackLayout>
- </StackLayout>
-
- <!-- Button -->
- <Button x:Name="solveButton"
- Text="Solve for x"
- FontSize="Large"
- IsEnabled="False"
- VerticalOptions="CenterAndExpand"
- HorizontalOptions="Center"
- Clicked="OnSolveButtonClicked" />
- <!-- Results section -->
- <StackLayout VerticalOptions="CenterAndExpand"
- HorizontalOptions="Center">
- <Label x:Name="solution1Label"
- HorizontalTextAlignment="Center" />
- <Label x:Name="solution2Label"
- HorizontalTextAlignment="Center" />
- </StackLayout>
- </StackLayout>
- </ContentPage>
标签,条目和按钮视图分为三个部分:顶部的数据输入,中间的按钮和底部的结果。请注意隐式Style条目中特定于平台的WidthRequest设置。这使每个条目的宽度为1英寸。
该程序提供了两种触发计算的方法:按键盘上的完成键,或按页面中间的按钮。这样的程序中的另一个选项是执行每次击键的计算(或者更准确,每个TextChanged
事件)。这可以在这里工作,因为重新计算非常快。但是,在本设计中,结果位于屏幕底部附近,并且在虚拟键盘处于活动状态时被覆盖,因此必须重新组织页面以使这种方案有意义。
QuadraticEquations程序使用TextChanged事件,但仅用于确定键入每个条目的文本的有效性。文本传递给Double.TryParse,如果方法返回false,则Entry文本显示为红色。 (在Windows 10Mobile上,只有当Entry失去输入焦点时才会显示红色文本。)此外,仅当所有三个Entry视图都包含有效的double值时,才会启用Button。这是显示所有程序交互的代码隐藏文件的前半部分:
点击(此处)折叠或打开
- public partial class QuadraticEquationsPage : ContentPage
- {
- public QuadraticEquationsPage()
- {
- InitializeComponent();
- // Initialize Entry views.
- entryA.Text = "1";
- entryB.Text = "-1";
- entryC.Text = "-1";
- }
- void OnEntryTextChanged(object sender, TextChangedEventArgs args)
- {
- // Clear out solutions.
- solution1Label.Text = " ";
- solution2Label.Text = " ";
- // Color current entry text based on validity.
- Entry entry = (Entry)sender;
- double result;
- entry.TextColor = Double.TryParse(entry.Text, out result) ? Color.Default : Color.Red;
- // Enable the button based on validity.
- solveButton.IsEnabled = Double.TryParse(entryA.Text, out result) &&
- Double.TryParse(entryB.Text, out result) &&
- Double.TryParse(entryC.Text, out result);
- }
- void OnEntryCompleted(object sender, EventArgs args)
- {
- if (solveButton.IsEnabled)
- {
- Solve();
- }
- }
- void OnSolveButtonClicked(object sender, EventArgs args)
- {
- Solve();
- }
- __
- }
Entry的Completed处理程序仅在启用Button时调用Solve方法,(如您所见)表示所有三个Entry视图都包含有效值。 因此,Solve方法可以安全地假设所有三个Entry视图都包含有效数字,这些数字不会导致Double.Parse引发异常。
Solve方法必然复杂,因为二次方程可能有一个或两个解,每个解可能有一个虚部和一个实部。 该方法将第二个解决方案的实际部分初始化为Double.NaN(“非数字”),并且只有在不再是这种情况时才显示第二个结果。仅当虚部非零时才显示虚部,并且加号或短划线(Unicode u2013)连接实部和虚部:
点击(此处)折叠或打开
- public partial class QuadraticEquationsPage : ContentPage
- {
- __
- void Solve()
- {
- double a = Double.Parse(entryA.Text);
- double b = Double.Parse(entryB.Text);
- double c = Double.Parse(entryC.Text);
- double solution1Real = 0;
- double solution1Imag = 0;
- double solution2Real = Double.NaN;
- double solution2Imag = 0;
- string str1 = " ";
- string str2 = " ";
-
- if (a == 0 && b == 0 && c == 0)
- {
- str1 = "x = anything";
- }
- else if (a == 0 && b == 0)
- {
- str1 = "x = nothing";
- }
- else
- {
- if (a == 0)
- {
- solution1Real = -c / b;
- }
- else
- {
- double discriminant = b * b - 4 * a * c;
- if (discriminant == 0)
- {
- solution1Real = -b / (2 * a);
- }
- else if (discriminant > 0)
- {
- solution1Real = (-b + Math.Sqrt(discriminant)) / (2 * a);
- solution2Real = (-b - Math.Sqrt(discriminant)) / (2 * a);
- }
- else
- {
- solution1Real = -b / (2 * a);
- solution2Real = solution1Real;
- solution1Imag = Math.Sqrt(-discriminant) / (2 * a);
- solution2Imag = -solution1Imag;
- }
- }
- str1 = Format(solution1Real, solution1Imag);
- str2 = Format(solution2Real, solution2Imag);
- }
- solution1Label.Text = str1;
- solution2Label.Text = str2;
- }
- string Format(double real, double imag)
- {
- string str = " ";
- if (!Double.IsNaN(real))
- {
- str = String.Format("x = {0:F5}", real);
- if (imag != 0)
- {
- str += String.Format(" {0} {1:F5} i",
- Math.Sign(imag) == 1 ? "+" : "\u2013",
- Math.Abs(imag));
- }
- }
- return str;
- }
- }
以下是几个解决方案: