Почему средство выбора в CollectionView устанавливает для привязки SelectedItem значение null?

У меня есть средство выбора внутри CollectionView, которое должно выбрать предопределенный элемент ColorNav, но при его запуске элемент не выбирается.

КСАМЛ:

        <StackLayout>
            <Label Text = "Players" />
            <CollectionView ItemsSource = "{Binding PlayerList}">
                <CollectionView.ItemTemplate>
                    <DataTemplate x:DataType = "model:Player">
                        <SwipeView>
                            <Border>
                                <Grid ColumnDefinitions = "*, *, *" ColumnSpacing = "1" >
                                    <Label Grid.Column = "0" Text = "{Binding Name}" />
                                    <Picker Grid.Column = "1" ItemsSource = "{Binding ColorsPicker, Source = {RelativeSource AncestorType = {x:Type viewmodel:MainViewModel}}}" ItemDisplayBinding = "{Binding Name}" SelectedItem = "{Binding ColorNav}"/>
                                    <Label Grid.Column = "2" Text = "{Binding ColorNav.Name}"/>
                                </Grid>
                            </Border>
                        </SwipeView>
                    </DataTemplate>
                </CollectionView.ItemTemplate>
            </CollectionView>
            <Button Text = "Save" Command = "{Binding SaveCommand}"/>
        </StackLayout>

С#

    public class Player
    {
        public string Name { get; set; } = default!;
        public int ColorId { get; set; } = default!;
        public Colour ColorNav { get; set; } = default!;
    }

    public class Colour
    {
        public int ColorId { get; set; }
        public string Name { get; set; } = default!;
    }

    public MainViewModel() {
            ColorsPicker = [
                new Colour {
                    ColorId = 1,
                    Name = "Red"
                },
                new Colour {
                    ColorId = 2,
                    Name = "Blue"
                },
                new Colour {
                    ColorId = 3,
                    Name = "Yellow"
                },
            ];

            PlayerList = [
                new Player {
                    Name = "John",
                    ColorId = 1,
                    ColorNav = ColorsPicker[0],
                },
                new Player {
                    Name = "Carla",
                    ColorId = 3,
                    ColorNav = ColorsPicker[2],
                },
            ];
    }

Во время отладки я вижу, что ColorNav загружается в BindingContext, но каким-то образом он становится нулевым при запуске страницы. Когда я нажимаю «Сохранить», ColorNav для каждого игрока имеет значение null. Если я удалю SelectedItem = "{Binding ColorNav}" из средства выбора, ColorNav останется таким, как ожидалось.У каждого игрока в BindingContext инициализирован ColorNav

Вы имеете в виду ColorNav инициализацию после привязки?

Shaw 21.07.2024 13:34

Я инициализирую ColorNav для каждого игрока в модели представления, прежде чем привязывать его к средству выбора. Я добавил некоторый контекст к вопросу.

luis_m 21.07.2024 19:20

Вы реализовали OnPropertyChanged в своей виртуальной машине и использовали наблюдаемые коллекции? Другая проблема может заключаться в том, что список ItemSource средства выбора отличается от списка SelectedItem, вызывающего проблему, проверьте это: stackoverflow.com/search?q=%5Bmaui%5Dpicker+collection

Shaw 22.07.2024 01:10

ItemsSource привязан к ObservableCollection<Colour> colorsPicker, и ColorNav тоже является Colour. Как я уже упоминал, SelectedItem ColorNav меняется на ноль при загрузке страницы. Я считаю, что это происходит потому, что он пытается загрузить SelectedItem перед загрузкой ItemsSource и, не найдя ничего, устанавливает для него значение null.

luis_m 22.07.2024 01:57
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
83
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете поместить переменную ColorsPicker и переменную ColorNav внутри модели Player.cs и реализовать интерфейс INotifyPropertyChanged для модели Player.cs.

public class Player: INotifyPropertyChanged
{
    public string Name { get; set; } = default!;
    public int ColorId { get; set; } = default!;
    // public Colour ColorNav { get; set; } = default!;

    public ObservableCollection<Colour> ColorsPicker { get; set; } = new ObservableCollection<Colour>();


    //add a property for the SelectedItem property of picker
    private Colour _colorNav;
    public Colour ColorNav
    {
        set
        {
            SetProperty(ref _colorNav, value);
        }
        get { return _colorNav; }
    }

    bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
    {
        if (Object.Equals(storage, value))
            return false;
        storage = value;
        OnPropertyChanged(propertyName);
        return true;
    }
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    public event PropertyChangedEventHandler PropertyChanged;
}

Кроме того, если мы хотим обновить пользовательский интерфейс (<Label Grid.Column = "2" Text = "{Binding ColorNav.Name}") при изменении выбранного элемента текущего средства выбора, нам также необходимо реализовать интерфейс INotifyPropertyChanged для модели Colour.cs

public class Colour: INotifyPropertyChanged
{
    public int ColorId { get; set; }
    //public string Name { get; set; } = default!;

    private string _name;
    public string Name
    {
        set
        {
            SetProperty(ref _name, value);
        }
        get { return _name; }
    }
    bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
    {
        if (Object.Equals(storage, value))
            return false;
        storage = value;
        OnPropertyChanged(propertyName);
        return true;
    }
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    public event PropertyChangedEventHandler PropertyChanged;

}

Затем мы можем инициализировать MainViewModel.cs следующим образом:

public class MainViewModel
{
    public ObservableCollection<Colour> ColorsPicker { get; set; } = new ObservableCollection<Colour>();
    public ObservableCollection<Player> PlayerList { get; set; } = new ObservableCollection<Player>();

    public MainViewModel() {

        ColorsPicker = [
     new Colour {
                ColorId = 1,
                Name = "Red"
            },
            new Colour {
                ColorId = 2,
                Name = "Blue"
            },
            new Colour {
                ColorId = 3,
                Name = "Yellow"
            },
        ];

        PlayerList = [
            new Player {
                Name = "John",
                ColorId = 1,
                ColorNav = ColorsPicker[0],
                ColorsPicker = ColorsPicker // initialize ColorsPicker
            },
            new Player {
                Name = "Carla",
                ColorId = 3,
                ColorNav = ColorsPicker[2],
                ColorsPicker = ColorsPicker // initialize ColorsPicker

            },
        ];

    }
}

И затем мы можем связать данные следующим образом:

    <CollectionView ItemsSource = "{Binding PlayerList}">
        <CollectionView.ItemTemplate>
            <DataTemplate x:DataType = "model:Player">
                <SwipeView>
                    <Border>
                        <Grid ColumnDefinitions = "*, *, *" ColumnSpacing = "1" >
                            <Label Grid.Column = "0" Text = "{Binding Name}" />
                            <!--<Picker Grid.Column = "1" ItemsSource = "{Binding ColorsPicker, Source = {RelativeSource AncestorType = {x:Type viewmodel:MainViewModel}}}" ItemDisplayBinding = "{Binding Name}" SelectedItem = "{Binding ColorNav}"/>-->
                            <Picker Grid.Column = "1" ItemsSource = "{Binding ColorsPicker}" ItemDisplayBinding = "{Binding Name}" SelectedItem = "{Binding ColorNav ,Mode=TwoWay}"/>

                            <Label Grid.Column = "2" Text = "{Binding ColorNav.Name}"/>
                        </Grid>
                    </Border>
                </SwipeView>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>

Спасибо, Джесси. Добавление ColorsPicker к каждому экземпляру Player решает проблему, хотя инициализация одной и той же коллекции для каждого экземпляра кажется странной, что может быть неэффективно (я думаю), но это работает :)

luis_m 23.07.2024 04:04

Другие вопросы по теме