Почему этот сборщик не выбирает предмет, как ожидалось? - PullRequest
0 голосов
/ 16 января 2020

Я пытаюсь сделать средство выбора, которое загружает ItemSource из списка и, в зависимости от внешнего события, изменить его SelectedIndex на основе Local.id, но то, что я пробовал до сих пор, не работает.

C# код:

public class Local
{
  public string cidade { get; set; }
  public int id { get; set; }
}

public int CidadeSelectedIndex{ get; set; }

        string jsonCidades;
        public async void CarregaCidades()
        {
            try
            {
                using (WebClient browser = new WebClient())
                {
                    Uri uriCidades = new Uri("xxxxxxx.php");
                    jsonCidades = await browser.DownloadStringTaskAsync(uriCidades);
                }
                var ListaCidades = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Local>>(jsonCidades);
                PickerCidades.ItemsSource = ListaCidades;
            }
            catch (Exception)
            {
                throw;
            }
        }


//In some moment of the execution, this code is called:

Local localizacao = JsonConvert.DeserializeObject<Local>(json);
if (localizacao.GetType().GetProperty("id") != null)
{
    /*CidadeSelectedItem = localizacao;  
     I tried that before with SelectedItem="{Binding CidadeSelectedItem, Mode=TwoWay}" */
     CidadeSelectedIndex = localizacao.id; // now trying this
}


Прежде, чем я пытался связать, используя ItemDisplayBinding = "{Binding ListaCidades.cidade, Mode = OneWay}", но так как он не работал, я начинаю использовать ItemSources = ListaCidades

Мой код XAML:

<Picker x:Name="PickerCidades"
        SelectedIndex="{Binding CidadeSelectedIndex, Mode=TwoWay}"
        Grid.Column="1" Grid.Row="0"
        SelectedIndexChanged="PickerCidades_SelectedIndexChanged">
</Picker>

Я думаю, что это не работает, потому что я настраиваю элементы с помощью ItemsSource. Я думаю, что мне нужно связать это с помощью xaml. Было бы неплохо помочь.

Ответы [ 2 ]

0 голосов
/ 16 января 2020

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

Мой макет xaml, подобный следующему коду.

    <StackLayout>
    <!-- Place new controls here -->
    <Picker x:Name="PickerCidades"
            ItemsSource="{ Binding locals}"
            SelectedIndex="{Binding CidadeSelectedIndex, Mode=TwoWay}"

            ItemDisplayBinding="{Binding cidade}" 
            Grid.Column="1" Grid.Row="0"
            SelectedIndexChanged="PickerCidades_SelectedIndexChanged">


    </Picker>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />

        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Label Text="CidadeSelectedIndex: " Grid.Column="0" Grid.Row="0"/>
        <Label Text="{Binding CidadeSelectedIndex}" Grid.Column="1" Grid.Row="0"/>
    </Grid>

</StackLayout>

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

    public partial class MainPage : ContentPage
{
    MyViewModel myViewModel;
    public MainPage()
    {
        InitializeComponent();
         myViewModel=  new MyViewModel();
        BindingContext = myViewModel;
    }

    private void PickerCidades_SelectedIndexChanged(object sender, EventArgs e)
    {

        var picker = (Picker)sender;
        int selectedIndex = picker.SelectedIndex;

        myViewModel.CidadeSelectedIndex = selectedIndex;

    }
}

Код MyViewMode. Я использую stati c данные для тестирования. Вы можете добиться динамического изменения интерфейса INotifyPropertyChanged.

    public  class MyViewModel : INotifyPropertyChanged
{


    int _cidadeSelectedIndex=1;
    public int CidadeSelectedIndex
    {
        set
        {
            if (_cidadeSelectedIndex != value)
            {
                _cidadeSelectedIndex = value;
                OnPropertyChanged("CidadeSelectedIndex");

            }
        }
        get
        {
            return _cidadeSelectedIndex;
        }
    }
    public ObservableCollection<Local> locals { get; set; }

    public MyViewModel()
    {
        locals = new ObservableCollection<Local>();

        locals.Add(new Local() { cidade=  "xxx0"  , id=  0 });
        locals.Add(new Local() { cidade = "xxx1", id = 1 });
        locals.Add(new Local() { cidade = "xxx2", id = 2 });
        locals.Add(new Local() { cidade = "xxx3", id = 3 });
        locals.Add(new Local() { cidade = "xxx4", id = 4 });

    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
0 голосов
/ 16 января 2020

Если цель состоит в том, чтобы изменить интерфейс пользователя из кода, вам необходимо иметь ViewModel, который реализует INotifyPropertyChanged (или наследует от базы, которая это делает). Тогда вместо связанного свойства SelectedIndex просто получить; если указано ниже, оно запускает событие PropertyChanged.

public int CidadeSelectedIndex{ get; set; }

Необходимо инициировать событие уведомления. Что-то в этом роде

public class MyViewModel : INotifyPropertyChanged  
{  

    public event PropertyChangedEventHandler PropertyChanged;  

    // This method is called by the Set accessor of each property.  
    // The CallerMemberName attribute that is applied to the optional propertyName  
    // parameter causes the property name of the caller to be substituted as an argument.  
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")  
    {  
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }  

    private int _cidadeSelectedIndex;

    public int CidadeSelectedIndex
    {
        get => _cidadeSelectedIndex;
        set {
            _cidadeSelectedIndex = value;
            NotifyPropertyChanged();
        }
    }
}  
...