c# - 如何通过单击按钮获取 Xamarin Forms 中的表单字段

标签 c# mobile mvvm xamarin.forms

我正在尝试通过使用 ICommand 界面单击按钮来获取 MVVM 设置中 View 中的字段值。最终目标是通过单击按钮获取这些字段,然后将这些字段保存到 SQLite DB 中。我正在提供与模型具有相同字段的 View 、代码隐藏和 ViewModel,以提供完整的图片,因为我正在寻找它们如何组合在一起并且在任何地方都找不到好的示例。许多链接返回到有关制作时钟的 MSDN 页面,但这对表单提交任务类型没有多大帮助。

这是 View :

<?xml version="1.0" encoding="UTF-8"?>
 <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="TermManager.Views.AddCourseView">
   <ContentPage.Content>
     <ScrollView>
        <StackLayout>
            <Label Text="Add Course" VerticalOptions="Center" HorizontalTextAlignment="Center" IsVisible="true" FontSize="Large" FontAttributes="Bold" TextColor="DarkBlue" Margin="10" />
            <Entry x:Name="CourseTitle" Placeholder="Course Title" Margin="3" />
            <Label Margin="3">Start Date</Label>
            <DatePicker x:Name="CourseStartDate" Margin="3" />
            <Label Margin="3">End Date</Label>
            <DatePicker x:Name="CourseEndDate" Margin="3" />
            <Picker x:Name="CourseStatus" Title="Course Status" Margin="3" TitleColor="DarkBlue">
                <Picker.ItemsSource>
                    <x:Array Type="{x:Type x:String}">
                        <x:String>in progress</x:String>
                        <x:String>completed</x:String>
                        <x:String>dropped</x:String>
                        <x:String>plan to take</x:String>
                    </x:Array>
                </Picker.ItemsSource>
            </Picker>
            <Entry x:Name="ProfessorName" Placeholder="Professor's Name" />
            <Entry x:Name="ProfessorPhone" Placeholder="Professor's Phone" />
            <Entry x:Name="ProfessorEmail" Placeholder="Professor's Email" />
            <Button x:Name="SaveCourseButton" Command="{Binding SaveCommand}" Text="Save" BackgroundColor="DarkBlue" TextColor="White" Margin="3" />
            <Button Text="Cancel" BackgroundColor="DarkRed" TextColor="White" Margin="3" Clicked="CancelCourseAddition" />
        </StackLayout>
    </ScrollView>
</ContentPage.Content>

隐藏代码:
using System;
using Xamarin.Forms;
using TermManager.Models;
using TermManager.ViewModels;
using System.Collections.Generic;

namespace TermManager.Views
{
public partial class AddCourseView : ContentPage
{
    public int TermId { get; set; }

    private AddCourseViewModel viewModel = new AddCourseViewModel();

    public AddCourseView()
    {
        InitializeComponent();
        BindingContext = viewModel;
    }

    protected async void CancelCourseAddition(object sender, EventArgs args)
    {
        await Navigation.PopAsync();
    }

    async void SaveButtonClicked(object sender, SelectedItemChangedEventArgs args)
    {
        var vm = sender as AddCourseViewModel;

        Course course = new Course
        {
            CourseStatus = vm.CourseStatus,
            CourseTitle = vm.CourseTitle,
            StartCourseDate = vm.StartCourseDate,
            EndCourseDate = vm.EndCourseDate,
            ProfessorEmail = vm.ProfessorEmail,
            ProfessorName = vm.ProfessorName,
            ProfessorPhone = vm.ProfessorPhone,
            TermId = vm.TermId
        };

        //viewModel.SaveNewTerm(course);
        await Navigation.PopAsync();
    }
}
}

查看型号:
using System;
using Xamarin.Forms;
using TermManager.Models;
using System.Windows.Input;
using System.ComponentModel;

namespace TermManager.ViewModels
{
    public class AddCourseViewModel : INotifyPropertyChanged
    {
        public int CourseId { get; set; }
        public int TermId { get; set; }
        public string CourseTitle { get; set; }
        public DateTime StartCourseDate { get; set; }
        public DateTime EndCourseDate { get; set; }
        public string CourseStatus { get; set; }
        public string ProfessorName { get; set; }
        public string ProfessorEmail { get; set; }
        public string ProfessorPhone { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;
        public ICommand SaveCommand
        {
            get
            {
                return new Command((e) =>
                {
                    var item = (e as Course);

                    var test = item.CourseTitle;
                });
            }
        }

        public AddCourseViewModel()
        {
        }

        //public async void SaveNewTerm(Course course)
        //{
        //    await App.Database.SaveCourseAsync(course);
        //}
    }
}

关于如何在不使用 x:Name="FieldName" 的情况下正确实现抓取这些字段的任何帮助、建议或技巧填充模型将不胜感激。

最佳答案

您正在寻找的是 Binding如果事实上你已经在使用它了CommandButton点击事件。

同样的方式,您可以将 ViewModel 中的属性绑定(bind)到 View 到控件的特定属性中。

例如,让我们以您的 Entry 之一为例。的:

<Entry x:Name="CourseTitle" 
    Text="{Binding CourseTitle, Mode=TwoWay}" 
    Placeholder="Course Title" 
    Margin="3" />

使用条目的文本属性,我们告诉绑定(bind) CourseTitle 的值从 View 模型。

您可以阅读有关数据绑定(bind)的更多信息 here

但是要使上述工作正常,您需要添加一个额外的步骤。您的 ViewModel 已经实现了 INotifyPropertyChanged但是您的属性必须在其值发生更改时通知。

像这样的东西:
public string _courseTitle;
public string CourseTitle
{
    get => _courseTitle;
    set
    {
        _courseTitle = value;
        RaisePropertyChanged(nameof(CourseTitle));
    }
}

您将对要绑定(bind)到 UI 的所有其他属性执行此操作,并通知您更改。

并添加此方法:
    protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

更多关于 Xamarin 中的 MVVM here

现在,您只需将相同的内容添加到 UI 中与您的 ViewModel 属性匹配的其余控件中。
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="TermManager.Views.AddCourseView">
<ContentPage.Content>
    <ScrollView>
        <StackLayout>
            <Label Text="Add Course" VerticalOptions="Center" HorizontalTextAlignment="Center" IsVisible="true" FontSize="Large" FontAttributes="Bold" TextColor="DarkBlue" Margin="10" />
            <Entry x:Name="CourseTitle" Text="{Binding CourseTitle, Mode=TwoWay}" Placeholder="Course Title" Margin="3" />
            <Label Margin="3">Start Date</Label>
            <DatePicker x:Name="CourseStartDate" Margin="3" />
            <Label Margin="3">End Date</Label>
            <DatePicker x:Name="CourseEndDate" Margin="3" />
            <Picker x:Name="CourseStatus" Title="Course Status" Margin="3" TitleColor="DarkBlue">
                <Picker.ItemsSource>
                    <x:Array Type="{x:Type x:String}">
                        <x:String>in progress</x:String>
                        <x:String>completed</x:String>
                        <x:String>dropped</x:String>
                        <x:String>plan to take</x:String>
                    </x:Array>
                </Picker.ItemsSource>
            </Picker>
            <Entry x:Name="ProfessorName" Text="{Binding ProfessorName, Mode=TwoWay}" Placeholder="Professor's Name" />
            <Entry x:Name="ProfessorPhone" Text="{Binding ProfessorPhone, Mode=TwoWay}" Placeholder="Professor's Phone" />
            <Entry x:Name="ProfessorEmail" Text="{Binding ProfessorEmail, Mode=TwoWay}" Placeholder="Professor's Email" />
            <Button x:Name="SaveCourseButton" Command="{Binding SaveCommand}" Text="Save" BackgroundColor="DarkBlue" TextColor="White" Margin="3" />
            <Button Text="Cancel" BackgroundColor="DarkRed" TextColor="White" Margin="3" Clicked="CancelCourseAddition" />
        </StackLayout>
    </ScrollView>
</ContentPage.Content>

大注:

有了这个,您将不再需要像在后面的代码中那样手动设置值。只需将值设置为 ViewModel 中的属性值,它们就会填充您的 View 。

希望这可以帮助。-

关于c# - 如何通过单击按钮获取 Xamarin Forms 中的表单字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58497221/

相关文章:

C# DataGridView - 透明图像

c# - Func<...> args 有 "unnamed"个参数。有没有办法给它们命名?

css - 移动视口(viewport)大小是基于浏览器还是屏幕分辨率?

mobile - 准备好为移动应用程序使用后端了吗?

c# - FocusManager.FocusedElement 在菜单中不起作用

android - 每次如何在koin中创建viewModel的新实例

WPF/MVVM - 如何在启动时执行命令?

c# - 如何在 C# 中从 JSON 自动生成/创建 SQL 服务器表

css - 我应该在 Phonegap/Cordova 应用程序上使用 CSS 重置还是规范化?

C# Mysql 和多线程?