【问题标题】:Why this picker is not selecting an item as expected?为什么此选择器未按预期选择项目?
【发布时间】:2020-05-02 18:00:22
【问题描述】:

我正在尝试做一个从 List 加载 ItemSource 并根据外部事件根据 Local.id 更改其 SelectedIndex 的选择器,但到目前为止我一直在尝试的方法不起作用。

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 绑定它。能帮上忙就好了。

【问题讨论】:

  • 你在使用 INotifyPropertyChanged 吗?
  • 没有。我正在调用一个更改 CidadeSelectedIndex 值的方法
  • 如果您不使用 INPC,更改 SelectedIndex 变量的值不会更新 UI
  • @Jason 如果我使用“INPC”,是否可以通过更改 SelectedIndex 来更改 ui?

标签: c# xamarin picker


【解决方案1】:

你想达到像下面的 GIF 一样的效果吗?

我的 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 代码。我使用静态数据进行测试。可以实现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));
    }
}

【讨论】:

  • @Sandro Benevides 这个问题有更新吗?如果回复有帮助,请将其标记为答案,它将帮助其他有类似问题的人。
【解决方案2】:

如果目标是从代码更改用户界面,您需要有一个实现 INotifyPropertyChanged 的​​ 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();
        }
    }
}  

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-19
    • 2017-09-18
    • 2016-06-22
    • 1970-01-01
    • 1970-01-01
    • 2018-10-22
    相关资源
    最近更新 更多