【问题标题】:Picker not updating when ItemsSource changedItemsSource 更改时选择器未更新
【发布时间】:2019-03-18 16:18:05
【问题描述】:

我有一个 Xamarin.Forms(3.2,最新版本)Picker 实现为

<Picker x:Name="ClassSelector"
            Title="Select Class"
            ItemsSource="{Binding Classrooms}"
            ItemDisplayBinding="{Binding ClassroomName}"
            SelectedItem="{Binding SelectedClassroom}">
</Picker>

BindingContext 就是这个 ViewModel:

public class ClassroomsViewModel : BaseViewModel
{
  public ObservableCollection<Classroom> Classrooms { get; set; }

  public ClassroomsViewModel()
  {
     Classrooms = new ObservableCollection<Classroom>(_ClassroomsRepository.GetAll());
  }
}

现在,当我在ViewModel 中添加教室时,Picker 会尽职尽责地将项目添加到其列表中:

 Classrooms.Add(new Classroom() { ClassroomName = "test" });   // this works fine

但如果我修改教室,Picker 不会更新其项目列表:

Classrooms[0].ClassroomName = "test";  // this doesn't have an effect,
                                       // although the value is set
                                       // in the ObservableCollection

我也尝试过显式调用:

    OnPropertyChanged();  // nothing
    OnPropertyChanged("Classrooms"); // nope

如果它很重要,Classroom 确实派生自 ObservableObject

public class Classroom : ObservableObject
{
   private string classroomName;

   public string ClassroomName { get => classroomName; set => SetProperty(ref classroomName, value); }
}

编辑,我在其中澄清这不是集合替换问题:

请注意,我不会用新的 ObservableCollection 替换 Classrooms 集合 - 就像在可能与我的问题相似的其他帖子中发生的那样。我只是修改该集合的成员之一。当此集合绑定到不同的控件(如ListView)时,它的行为与预期完全一样——ListView 更新以反映新的ClassroomName

谁能指出我做错了什么?

【问题讨论】:

标签: xamarin.forms observablecollection


【解决方案1】:

通常,当我们使用绑定时,我们希望目标(选择器项)与绑定源(在本例中为 Classroom 对象)保持同步 - 因此,按照设计,您的代码是正确的.

但是,在 XF github 中深入研究 Picker 源代码后 - 在从 Binding 中提取第一个值后,它似乎取消了绑定/属性更改的订阅。 Here you can see the explicit call to UnApply() 绑定,随后绑定到选择器项目显示名称的绑定表达式。

CustomerViewModel(而不是Customer)上调用OnPropertyChanged("Classrooms"); 在技术上应该可行。或者,您可以尝试从集合中删除修改后的Customer 对象,然后在同一索引处重新添加以解决此问题。这两个操作都会触发ResetItems() - 这反过来又会触发picker-item's display name 的刷新。

【讨论】:

  • 谢谢你。在视图模型上使用OnPropertyChanged("Classrooms") 似乎不会触发ResetItems(),但是删除/替换项目解决方法可以解决这个问题。
  • 我假设 UnApply() 调用是 Xamarin 控件如何将自己绑定到 OneWay 的?这意味着 Picker 的 ItemsSource 绑定是 only OneWay。文档中没有说明这一点,因此我将其作为错误报告归档(或者至少需要更新文档)。
  • 问题已添加到 Xamarin.Forms:github.com/xamarin/Xamarin.Forms/issues/4077
  • @GrahamCharles:似乎 UnApply 几乎断开了源和目标之间的绑定连接。这与OneWay 模式不同,您希望更改通知始终从源流向目标。你说的是OneTime 模式吗?
  • 话虽如此,感谢您报告问题。至少应该记录在案。
【解决方案2】:

出于某种原因,将源设置为 null 然后重置它对我有用:

var items = picker.ItemsSource as List<string>;
items.Add("item");
picker.ItemsSource = null;
picker.ItemsSource = items;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-09
    • 2020-01-15
    • 1970-01-01
    • 2021-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多