MVVM динамически добавляет элементы в scrollview - PullRequest
2 голосов
/ 13 февраля 2020

Извиняюсь заранее, если об этом спрашивали раньше. Самым близким, что я нашел, было ( Как использовать вертикальное представление прокрутки для отображения обязательных данных ), что выглядит многообещающе, хотя я не уверен, что это будет работать, потому что я понимаю, что шаблон, как имя и определение подразумевает, должно следовать заданному шаблону c и, следовательно, не может быть динамическим c.

Моя проблема : Я пытаюсь переписать часть нашего кода, чтобы более точно следовать шаблонам MVVM, это, конечно, означает сделать представление настолько глупым, насколько это возможно. На мой взгляд (xaml.cs) у меня есть код, который делает следующее:

 foreach(var tuple in itemsToAdd)
            {
                var formEntry = formEntries.First(x => x.FormEntryId == tuple.Item1);
                var controlType = formatting.GetControlType(formEntry.FormAnswerName,
                                                         formEntry.CustomEntryIdentifier);

                if (formEntry.Type == 0) {
                    switch (controlType) {
                        case CustomControl.Duration:
                            CustomFields.Children.Add(new DurationView(formEntry.FormEntryId, viewModel));
                            break;
                        case CustomControl.TextField:
                        case CustomControl.InputField:

                            CustomFields.Children.Add(new InputFieldView(formEntry.FormEntryId, viewModel));
 .....//continues like this for different controls.

Список itemsToAdd определен в моей модели представления, его работа заключается в том, чтобы выяснить, какие элементы из пользовательского шаблона нужно отображать. Это, конечно, хорошо, поскольку, согласно моему пониманию MVVM, модель представления - это то, что должно контролировать поведение (в данном случае, что отображать), а пользовательский интерфейс просто обрабатывает отображение полей.

Мне было интересно, возможно ли также позволить модели представления обрабатывать, по сути, настройку источника элемента представления прокрутки, как мы делаем, когда создаем источник элемента для представления списка (скажем, как список доступных шаблонов), так как каждый из элементов управления является пользовательским представлением, которое мы создали, я не вижу выполнимого способа достичь этого, поскольку он не может (насколько я понимаю) следовать шаблону, поскольку каждый элемент управления является отличается, и я не хочу, чтобы моя модель представления возвращала фактический объект представления, поскольку это нарушило бы принципы MVVM.

По сути, это: я неправильно понимаю MVVM в Xamarin, и это нормально для xaml код, чтобы добавить элементы, как то, что я показываю в фрагменте кода.

Извиняюсь, если неясно, о чем я прошу!

Ответы [ 2 ]

2 голосов
/ 13 февраля 2020

Я не уверен, что понимаю настоящую проблему. Вы пытаетесь показать разные интерфейсы для каждого элемента itemsToAdd в соответствии со свойством Type?

Если это проблема, вы можете связать всю коллекцию к элементу управления ListView (или к тому, что вы используете) и используйте DataTemplateSelector для выбора нужного интерфейса. Ссылка

Просмотр Вы можете обратиться к предыдущей ссылке. Это будет выглядеть так:

<ListView ItemsSource="{Binding FormEntries}" DataTemplateSelector="{StaticResource dataTemplateSelectorName}"/>

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

ViewModel Предполагается, что тип вашего объекта называется FormEntry

private ObservableCollection<FormEntry> _formEntries;
public ObservableCollection<FormEntry> FormEntries
{
    get => _formEntries;
    set
    {
        _formEntries = value;
        // Call the 'RaisePropertyChanged' of the framework you are using
    }
}

...
FormEntries = new ObservableCollection<FormEntry>(itemsToAdd);
...

DataTemplateSelector См. Ссылку для создания класса, который расширяет DataTemplateSelector и переопределяет метод OnSelectTemplate, чтобы определить бизнес-логики c для выбора необходимого шаблона пользовательского интерфейса

0 голосов
/ 24 февраля 2020

Итак, я смог понять, как это сделать, большое спасибо Красти за то, что он указал мне на правильные источники.

Мне пришлось создать свой DataTemplateSelector,

public class MyTemplate: DataTemplateSelector
    {
        public DataTemplate InputFieldTemplate { get; set; }
        public DataTemplate EmptyTemplate { get; set; }
        public DataTemplate DurationTemplate { get; set; }
        public DataTemplate SignatureDetailTemplate {get; set;}
        public DataTemplate SignaturePhoneTemplate { get; set; }
        public DataTemplate DateTemplate { get; set; }


        protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
        {
            try
            {
                ControlsViewModel viewModel = item as ControlsViewModel;

                if (viewModel == null)
                {
                    return EmptyTemplate;
                }


                if (viewModel.ControlType == Enums.CustomControl.InputField || viewModel.ControlType == Enums.CustomControl.TextField)
                    return InputFieldTemplate;
                if (viewModel.ControlType == Enums.CustomControl.Duration)
                {
                    return DurationTemplate;
                }
                if (viewModel.ControlType == Enums.CustomControl.Signature)
                {
                    if(string.IsNullOrEmpty(viewModel.Disclaimer))
                    {
                        return SignatureDetailTemplate;
                    }

                    return SignaturePhoneTemplate;
                }



                return EmptyTemplate;
            }
            catch
            {
                throw;
            }
        }
    }

Затем я создаю для него соответствующий словарь (в данном случае ResourceDictionary.xaml)

<DataTemplate x:Key="EmptyTemplate">
    <ViewCell>
        <BoxView></BoxView>
    </ViewCell>
</DataTemplate>


<DataTemplate x:Key="InputFieldTemplate">
    <ViewCell>


        <StackLayout Orientation="Vertical" 
                         Padding="0, 20, 0, 0"
                         HorizontalOptions="FillAndExpand"
                         VerticalOptions="StartAndExpand">

        <Label Text="{Binding Label}"
                      FontAttributes="Bold"
                      TextColor="Black"
                      FontSize="14"
                      VerticalOptions="Start"
                      HorizontalOptions="FillAndExpand"/>


        <StackLayout
            HorizontalOptions="FillAndExpand"
            VerticalOptions="Start"
            Spacing="0"
            Orientation="Vertical">

            <Editor

                Text="{Binding Answer}"
                TextColor="Black"
                AutoSize="TextChanges" 
                IsTextPredictionEnabled="False"
                IsSpellCheckEnabled="False"
                BackgroundColor="White"
                FontSize="14"
                VerticalOptions="Start"
                HorizontalOptions="FillAndExpand"/>

            <BoxView HeightRequest="1"
                 BackgroundColor="{Binding FieldColor}" 
                 Margin="0"
                 HorizontalOptions="FillAndExpand"
                 VerticalOptions="Start"/>

        </StackLayout>
    </StackLayout>
    </ViewCell>
</DataTemplate>    

Наконец, с учетом того, что я хочу его использовать, я добавляю его следующим образом:

<ListView ItemsSource="{Binding NoteObjects}" ItemTemplate="{StaticResource DataTemplateSelector}"/>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...