Xamarin Picker показывает нежелательные элементы в пользовательском интерфейсе - PullRequest
0 голосов
/ 22 октября 2019

Выдернуть мои волосы в точке. My Picker показывает раздражающую строку в пользовательском интерфейсе и / или свойстве Title Picker, если оно включено. Я просто хочу сборщик, а не материал, отображаемый в пользовательском интерфейсе под ним. Есть идеи, как этого добиться? Нужно ли использовать пользовательский рендерер или мне чего-то не хватает?

Примечание : список намеренно пуст в следующих примерах.

Безназвание, я нажимаю кнопку «Существующий», отображается строка, нажимаю ее снова, и появляется модальное значение:

Initial screen, without title. Line appears after first click, without title. After clicking again the line stays and the modal appears, without title.

With the title, I click the Existing button, the line and title show, click it again and the modal appears:

Initial screen, with title. Line appears after first click, with title. After clicking again the line stays and the modal appears, with title.

Don't know why I have to click the button twice. But it's only on the initial page load. If I exit the modal and click the button again, it immediately appears, no double-click. Not sure if that's related to my original question, but thought I'd include it for additional information.

NewSubjectPage.xaml (chopped for brevity)


        Выберите график

NewSubjectPage.xaml.cs (для краткости)

public partial class NewSubjectPage : ContentPage
{
    private string chartName;
    private readonly NewSubjectViewModel _viewModel;

    public string ChartName
    {
        get => chartName;
        private set
        {
            chartName = value;
            OnPropertyChanged();
        }
    }

    public NewSubjectPage()
    {
        InitializeComponent();

        BindingContext = _viewModel = new NewSubjectViewModel();

        chartName = "";
    }

    private void NewSubjectExisChrtBtn_Clicked(object sender, EventArgs e)
    {
        _viewModel.LoadChartsCommand.Execute(null);
        NewSubjectExisChrtPck.IsVisible = true;
        NewSubjectExisChrtPck.Focus();
    }

    private void NewSubjectExisChrtPck_SelectedIndexChanged(object sender, EventArgs e)
    {
        var picker = (Picker)sender;
        int selectedIndex = picker.SelectedIndex;

        if (selectedIndex != -1)
        {
            ChartName = picker.Items[picker.SelectedIndex];
        }
    }

    private void NewSubjectExisChrtPck_Unfocused(object sender, FocusEventArgs e)
    {
        NewSubjectExisChrtPck.IsVisible = false;
        NewSubjectExisChrtPck.Unfocus();
    }
}

NewSubjectViewModel.cs (для краткости)

class NewSubjectViewModel : BaseViewModel
{
    private ObservableCollection<Chart> charts;

    public ObservableCollection<Chart> Charts
    {
        get { return charts; }
        private set
        {
            charts = value;
            OnPropertyChanged();
        }
    }

    public Command LoadChartsCommand { get; set; }

    public NewSubjectViewModel()
    {
        LoadChartsCommand = 
            new Command(
                async () => await ExecuteLoadChartsCommand()
            );
    }

    private async Task ExecuteLoadChartsCommand()
    {
        try
        {
            IndicatorRunning = true;

            var list = await App.Database.GetChartsAsync();
            Charts = new ObservableCollection<Chart>(list);
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex);
        }
    }
}

Спасибо за вашу помощь! Дайте мне знать, если вам нужно что-то еще увидеть.

1 Ответ

1 голос
/ 23 октября 2019

Во-первых, я не смог воспроизвести проблему с модалом, которая не отображалась до второго нажатия кнопки. Возможно, вам придется предоставить больше кода для этого. Чтобы даже использовать ваш пример кода, мне пришлось заменить var list = await App.Database.GetChartsAsync(); чем-то другим, чтобы имитировать долгосрочную задачу, которая возвращает пустой список. Также пришлось создать тип Chart со свойством Name. Не говоря уже о BaseViewModel. В будущем, пожалуйста, предоставьте весь код для воспроизведения проблемы, чтобы от человека, который пытается вам помочь, требовалась минимальная работа. Существует концепция переполнения стека, называемая MCVE (минимальный, полный, проверяемый пример): http://stackoverflow.com/help/mcve

При этом, возможно, первый щелчок фактически фокусирует эмулятор и делает его активным приложением, а затем второйэто первый фактический клик по кнопке? Это я могу воспроизвести. Таким образом, если эмулятор не является приложением переднего плана, вы должны щелкнуть его один раз, чтобы сделать его активным, и тогда ваше приложение будет обрабатывать щелчки.

Что касается нежелательного пользовательского интерфейса, вы понимаете, что интерфейс выбора - это, по сути, кликабельная метка, которая при нажатии отображает фактический модальный режим выбора? Таким образом, когда вы делаете его видимым, то, что вы делаете видимым, это UI надписи, у которого есть строка и заголовок (если он установлен), и когда вы фокусируете эту метку, то отображается фактическое диалоговое окно выбора. Если вы вообще не хотите видеть метку пользовательского интерфейса, зачем делать ее видимой? Вы можете сфокусировать его, не делая его видимым, поэтому просто удалите строку NewSubjectExisChrtPck.IsVisible = true;

В качестве примечания, когда вы вызываете _viewModel.LoadChartsCommand.Execute(null);, который вызывает асинхронный метод, var list = await App.Database.GetChartsAsync();, поэтому LoadChartsCommand возвращаетдо того, как вы установите свойство Charts, а также код, следующий за вызовом _viewModel.LoadChartsCommand.Execute(null);, также выполняется до того, как LoadChartsCommand действительно завершится, так что вы делаете средство выбора видимым и фокусируете его до завершения LoadChartsCommand, так что если вызагружали фактические предметы для показа сборщика, они могут быть там не в первый раз. Может быть, это всего лишь пример кода, но я не вижу смысла использовать команду здесь, скорее, вам следует просто вызвать ожидаемое задание. Вы не привязаны к LoadChartsCommand, поэтому я не вижу смысла для вас даже использовать Command в этом сценарии. Вместо этого я предлагаю сделать ExecuteLoadChartsCommand публичным и вызвать его напрямую, например:

private async void NewSubjectExisChrtBtn_Clicked(object sender, EventArgs e)
{
    //_viewModel.LoadChartsCommand.Execute(null); // Returns immediately, so picker not loaded with items yet.
    await _viewModel.ExecuteLoadChartsCommand(); // Waits for method to finish before before presenting the picker.
    //NewSubjectExisChrtPck.IsVisible = true;
    NewSubjectExisChrtPck.Focus();
}
...