Множественное поведение в записи (формы Xamarin) - PullRequest
0 голосов
/ 17 марта 2020

У меня было много проблем с реализацией нескольких вариантов поведения для записи

Я хочу реализовать проверку пользовательского ввода, если пользователь вводит целые числа, десятичные числа, дату и текст

Надеюсь Вы можете помочь или прислать примеры

1 Ответ

0 голосов
/ 17 марта 2020

Вам очень повезло, потому что совсем недавно я реализовал очень похожую вещь:

 private FormQuestion formModel {get;set;}
 public Form()
    {
        InitializeComponent();
        //Hook up events, set layout of main Stack
        CreateViews(formModel);
        mainStack.Orientation = StackOrientation.Vertical;
        mainStack.VerticalOptions = LayoutOptions.FillAndExpand;
        mainStack.HorizontalOptions = LayoutOptions.FillAndExpand;
    }
    #endregion
    /// <summary>
    /// Method that returns Stack layout that contains control required for filling up the form if QuestionType is Text.
    /// This method creates StackLayout, Label and Entry then returns it.
    /// </summary>
    /// <param name="formQuestions"></param>
    /// <returns></returns>
    private StackLayout CreateQuestionStackText(FormQuestion formQuestions)
    {
        StackLayout stack = new StackLayout
        {
            Orientation = StackOrientation.Horizontal,
            VerticalOptions = LayoutOptions.Center,
            HorizontalOptions = LayoutOptions.FillAndExpand
        };
        Label label = new Label
        {
            HorizontalOptions = LayoutOptions.Start,
            VerticalOptions = LayoutOptions.CenterAndExpand
        };
        label.SetBinding(Label.TextProperty, "Text");
        Entry entry = new Entry
        {
            HorizontalOptions = LayoutOptions.EndAndExpand,
            VerticalOptions = LayoutOptions.CenterAndExpand,
            WidthRequest = 200
        };
        entry.SetBinding(Entry.TextProperty, "Value");
        stack.Children.Add(label);
        stack.Children.Add(entry);
        return stack;

    }
    /// <summary>
    /// Method that returns Stack layout that contains control required for filling up the form if QuestionType is Number. 
    /// This method creates StackLayout, Label and Entry that enforces Numerical Keyboard then returns it.  
    /// </summary>
    /// <param name="formQuestions"></param>
    /// <returns></returns>
    private StackLayout CreateQuestionStackNumber(FormQuestion formQuestions)
    {
        StackLayout stack = new StackLayout
        {
            Orientation = StackOrientation.Horizontal,
            VerticalOptions = LayoutOptions.Center,
            HorizontalOptions = LayoutOptions.FillAndExpand
        };
        Label label = new Label
        {
            HorizontalOptions = LayoutOptions.Start,
            VerticalOptions = LayoutOptions.CenterAndExpand
        };
        label.SetBinding(Label.TextProperty, "Text");
        Entry entry = new Entry
        {
            HorizontalOptions = LayoutOptions.EndAndExpand,
            VerticalOptions = LayoutOptions.CenterAndExpand,
            Keyboard = Keyboard.Numeric,
            WidthRequest = 200
        };
        entry.SetBinding(Entry.TextProperty, "Value");
        stack.Children.Add(label);
        stack.Children.Add(entry);
        return stack;
    }
    /// <summary>
    /// Method that returns Stack layout that contains control required for filling up the form if QuestionType is DropDown
    /// This method creates StackLayout, Label and BindablePicker, which is custom Picker I've created to be able to get work with MVVM, then returns it.
    /// </summary>
    /// <param name="formQuestions"></param>
    /// <returns></returns>
    private StackLayout CreateQuestionStackDropDown(FormQuestion formQuestions)
    {
        StackLayout stack = new StackLayout
        {
            Orientation = StackOrientation.Horizontal,
            VerticalOptions = LayoutOptions.Center,
            HorizontalOptions = LayoutOptions.FillAndExpand
        };
        Label label = new Label 
        {
            HorizontalOptions = LayoutOptions.Start,
            VerticalOptions = LayoutOptions.CenterAndExpand
        };
        label.SetBinding(Label.TextProperty, "Text");
        BindablePicker picker = new BindablePicker();
        picker.HorizontalOptions = LayoutOptions.EndAndExpand;
        picker.BindingContext = this;
        var bind = this.BindingContext;
        var strings = formQuestions.DataSource.Values;
        var listOfStrings = strings.Split(';');
        List<string> result = new List<string>();
        foreach (var item in listOfStrings)
        {
            result.Add(item);
        }
        picker.ItemsSource = result;
        picker.SelectedIndexChanged += Picker_SelectedIndexChanged;
        //picker.SetBinding(BindablePicker.DisplayMemberPathProperty, new Binding( "Values", BindingMode.TwoWay, new ValuesToListOfStringsConverter(), null));
        picker.SetBinding(BindablePicker.SelectedItemProperty, "Value");
        picker.WidthRequest = 200;
        stack.Children.Add(label);
        stack.Children.Add(picker);
        return stack;
    }
    /// <summary>
    /// Method that returns Stack layout that contains control required for filling up the form if QuestionType is Data
    /// This method creates StackLayout, Label and DataPicker and returns it.
    /// </summary>
    /// <param name="formQuestions"></param>
    /// <returns></returns>
    private StackLayout CreateQuestionStackDate(FormQuestion formQuestions)
    {
        StackLayout stack = new StackLayout
        {
            Orientation = StackOrientation.Horizontal,
            VerticalOptions = LayoutOptions.Center,
            HorizontalOptions = LayoutOptions.FillAndExpand
        };
        Label label = new Label
        {
            HorizontalOptions = LayoutOptions.Start,
            VerticalOptions = LayoutOptions.CenterAndExpand
        };
        label.SetBinding(Label.TextProperty, "Text");
        DatePicker datePicker = new DatePicker();
        datePicker.HorizontalOptions = LayoutOptions.EndAndExpand;
        datePicker.SetBinding(DatePicker.DateProperty, "Value");
        stack.Children.Add(label);
        stack.Children.Add(datePicker);
        return stack;
    }
    /// <summary>
    /// Little hack, that unfortunately I had to implement. Because DropDown contains list of DataSource Properties that is essentially array of objects, I had to work around with pulling data of selected item and only
    /// get Values property value. This couldnt be bound correctly, because Values are expecting to be string, but SelectedItem property of picker is an actuall full Object of DataSource. 
    /// I Could probably work around it by Implementing Converter, but Converter will have more code, and I couldnt be bothered. 
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void Picker_SelectedIndexChanged(object sender, EventArgs e)
    {
        //Cast sender object to BindablePicker (since sender is BindablePicker)
        var picker = (BindablePicker)sender;
        ///Get SelectedItem Value and cast it to DataSource (since SelectedItem is DataSource)
        var value = (string)picker.SelectedItem;
        // Assign Values value back to My Collection
        ((FormQuestion)BindingContext).Value = value;
    }
    /// <summary>
    /// Determine which stack should be created, depending on QuestionType
    /// </summary>
    /// <param name="formModel"></param>
    private void CreateViews(FormQuestion formModel)
    {
        StackLayout newStack = new StackLayout();
                switch (formModel.QuestionType.Name)
                {
                    case "text":
                    newStack.Children.Add(CreateQuestionStackText(formModel));
                        break;
                    case "number":
                    newStack.Children.Add(CreateQuestionStackNumber(formModel));
                        break;
                    case "dropDown":
                    newStack.Children.Add(CreateQuestionStackDropDown(formModel));
                        break;
                    case "date":
                    newStack.Children.Add(CreateQuestionStackDate(formModel));
                        break;
                    default:
                    newStack.Children.Add(CreateQuestionStackText(formModel));
                    break;
                }
        this.mainStack.Children.Add(newStack);
    }
    #endregion

    public class FormQuestion
{
    public int FormQuestionId { get; set; }
    public string Text { get; set; }
    public string Value { get; set; }
    public int QuestionTypeId { get; set; }
    public virtual QuestionType QuestionType { get; set; }
    public int FormId { get; set; }
    public Form Form { get; set; }
    public DataSource DataSource { get; set; }
}
   public class QuestionType
{
    public int QuestionTypeId { get; set; }

    public string Name { get; set; }
}

Это будет ваш Xaml.

            <StackLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
    <Frame BorderColor="Gray" CornerRadius="2" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" >
    <StackLayout Orientation="Vertical" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" x:Name="mainStack">
    </StackLayout>
    </Frame>
    </StackLayout>

Вам нужно будет немного изменить, чтобы соответствовать ваша цель, но я предоставил вам мою реализацию, так что у вас есть базовые знания и понимание того, что вы должны делать. Также имейте в виду, что это было сделано для использования MVVM. Я также вычеркнул некоторые методы, которые не имеют отношения к делу. BindablePicker является расширенной версией средства выбора, поскольку стандартный инструмент выбора форм Xamarin не имеет привязываемых свойств. Основная цель моего кода состояла в том, чтобы динамически создавать различные типы записей, средств выбора, даты и т. Д. c в зависимости от типа формы, получаемого из серверной части, и связывать их с ViewModel внутри ListView.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...