Проблема при использовании itemssource для сохранения и извлечения элемента, выбранного в xamarin - PullRequest
1 голос
/ 05 февраля 2020

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

В двух фрагментах ниже показана таблица данных для типа выпадающего вопроса. Первый показывает, чего я надеюсь достичь с помощью источника элементов, который выбирает варианты выпадающего списка и позволяет сохранить их. Но это не работает - он показывает опции, которые выбираются при нажатии на запись, и затем они добавляются в поле. После сохранения страницы и повторного открытия предыдущий выбор возвращается к пустому.

Questions.xaml - раскрывающийся шаблон из источника элементов (не работает)

<DataTemplate x:Key="DropdownTemplate">
     <StackLayout IsVisible="{Binding IsVisible}" HeightRequest="{Binding RowHeight}" Padding="{Binding IndentPadding}">
         <StackLayout Orientation="Horizontal">
             <Label Text="{Binding Text}" StyleClass="QuestionText"/>
                <Picker SelectedItem="{Binding Answer, Converter={StaticResource DropDownConverter},Mode=TwoWay}" StyleClass="QuestionAnswer" WidthRequest="100" ItemsSource="{Binding DropdownOptions}"></Picker>
            </StackLayout>
            <BoxView StyleClass="ListBreak"/>
        </StackLayout>
    </DataTemplate>

Questions.xaml - раскрывающийся шаблон (работающий)

<DataTemplate x:Key="DropdownTemplate">
     <StackLayout IsVisible="{Binding IsVisible}" HeightRequest="{Binding RowHeight}" Padding="{Binding IndentPadding}">
         <StackLayout Orientation="Horizontal">
             <Label Text="{Binding Text}" StyleClass="QuestionText"/>
                <Picker SelectedItem="{Binding Answer, Converter={StaticResource DropDownConverter},Mode=TwoWay}" StyleClass="QuestionAnswer" WidthRequest="100" ItemsSource="{Binding DropdownOptions}">
                <Picker.ItemsSource>
                   <x:Array Type="{x:Type x:Int32}">
                      <x:Int32>1</x:Int32>
                      <x:Int32>2</x:Int32>
                   </x:Array>
                </Picker.ItemsSource>
                </Picker>
            </StackLayout>
            <BoxView StyleClass="ListBreak"/>
        </StackLayout>
    </DataTemplate>

Из отладки Я вижу, что нажатие на эту опцию и сохранение работает, как и ожидалось, но после повторного открытия страницы, содержащей вновь сохраненную запись, значение корректно попадает в конвертер - преобразуется - и, кажется, завершилось и сработало, как и ожидалось. Затем преобразователь снова запускается, и поле «значение» становится пустым, что затем устанавливает запись равной нулю, изменяя предыдущий выбор. (Жестко закодированная версия правильно работает с доступом к конвертеру, как и ожидалось)

Выпадающий конвертер

public class DropDownConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value != null)
        {
            int final = Int32.Parse(value.ToString());
            return final;
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value != null)
        {
            string final = value.ToString();
            return final;
        }
        return null;
    }
}

Пример вопроса (из модели)

[QuestionAttribute(dropdownOptions = new List<int> ( 1, 2)]
[Display(Name = "QuestionName")]
public int? Question { get; set; }

QuestionAttribute

[AttributeUsage(AttributeTargets.Property)]
public class QuestionAttribute : Attribute
{
    public int[] dropdownOptions { get; set; }
}

Извините, если что-то из этого не понятно, я буду рад ответить на дополнительные вопросы или предоставить изображения приложения, если это необходимо. Я довольно уверен, что проблема заключается в процессе получения источника данных из атрибута вопроса данного конкретного вопроса. Есть лучший способ сделать это? Должен ли он быть в списке?

Любая помощь очень ценится!

Ответы [ 2 ]

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

Спасибо Леону за код, который вы указали выше. Извиняюсь за плохое объяснение того, что мне было нужно. Я унаследовал это приложение от сторонней компании, и сейчас я много чего пытаюсь втиснуть в этот вопрос. Я думаю, что мое плохое объяснение и отсутствие каких-либо изображений, показывающих, что я работал, привело вас на неверный путь. Я буду помнить об этом в следующий раз и обязательно запишу, что приложение делает в то время, чтобы помочь вам в этом.

Раздражающе кажется, что это ошибка в xamarin, которая вызывала мою проблему. Эта ссылка Вот суть. По какой-то странной причине, переупорядочение свойств внутри сборщика решает проблему.

<Picker ItemsSource="{Binding DropdownOptions}" SelectedItem="{Binding Answer, Converter={StaticResource DropDownConverter},Mode=TwoWay}" StyleClass="QuestionAnswer" WidthRequest="100" >

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

Большое спасибо за вашу помощь, она помогла мне в пути!

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

Хотите ли вы добиться результата, подобного следующему GIF?

enter image description here

Я не знаю, какие именно c StyleClass вы использовали. Я удаляю их все.

Я использовал Mvvm для достижения этой цели. Вы можете обратиться к нему.

Прежде всего, это макет.

 <ContentPage.Resources>
    <ResourceDictionary>
        <local:DropDownConverter x:Key="DropDownConverter" />
    </ResourceDictionary>
</ContentPage.Resources>

<StackLayout>
    <!-- Place new controls here -->
    <ListView Margin="0,20,0,0" ItemsSource="{Binding myModels}">
        <ListView.ItemTemplate>
            <DataTemplate >
                <ViewCell>
                    <StackLayout IsVisible="{Binding IsVisible}" HeightRequest="{Binding RowHeight}" Padding="{Binding IndentPadding}">
                        <StackLayout Orientation="Horizontal">
                            <Label Text="{Binding Text}" />
                            <Picker  ItemsSource="{Binding DropdownOptions}" SelectedItem="{Binding Answer,Converter={StaticResource DropDownConverter}, Mode=TwoWay}"  WidthRequest="100" ></Picker>
                        </StackLayout>
                        <BoxView />
                    </StackLayout>
                </ViewCell>

            </DataTemplate>

        </ListView.ItemTemplate>

    </ListView>
</StackLayout>

Вот код фона макета.

  public MainPage()
 {
        InitializeComponent();
        BindingContext = new MyViewModel();
 }

Вот моя модель представления.

     public class MyViewModel
{
    public ObservableCollection<MyModel> myModels { get; set; }
    public MyViewModel()
    {
        myModels = new ObservableCollection<MyModel>();
        myModels.Add(new MyModel() { Answer=1, DropdownOptions= new int[]{ 1, 2 ,3, 4 }, IndentPadding=3, IsVisible=true, RowHeight=30, Text="test1" });
        myModels.Add(new MyModel() { Answer = 2, DropdownOptions = new int[] { 1, 2, 3, 4 }, IndentPadding = 3, IsVisible = true, RowHeight = 30, Text = "test2" });

        myModels.Add(new MyModel() { Answer = 1, DropdownOptions = new int[] { 1, 2, 3, 4 }, IndentPadding = 3, IsVisible = true, RowHeight = 30, Text = "test3" });
        myModels.Add(new MyModel() { Answer = 3, DropdownOptions = new int[] { 1, 2, 3, 4 }, IndentPadding = 3, IsVisible = true, RowHeight = 30, Text = "test4" });
        myModels.Add(new MyModel() { Answer = 2, DropdownOptions = new int[] { 1, 2, 3, 4 }, IndentPadding = 3, IsVisible = true, RowHeight = 30, Text = "test5" });

        myModels.Add(new MyModel() { Answer = 4, DropdownOptions = new int[] { 1, 2, 3, 4 }, IndentPadding = 3, IsVisible = true, RowHeight = 30, Text = "test6" });

}
}

Вот моя модель.

     public class MyModel
{
    public bool IsVisible { get; set; }
    public int RowHeight { get; set; }
    public int IndentPadding { get; set; }

    public string Text { get; set; }
    public int[] DropdownOptions { get; set; }

    public int Answer { get; set; }
}
...