【问题标题】:Xamarin Picker bindingXamarin 选择器绑定
【发布时间】:2020-01-15 10:02:46
【问题描述】:

我是否遗漏了什么,或者还有更多我没有得到的东西。我正在开发一个移动应用程序,并且必须使用选择器从数据表中进行选择。首先,我有许多基于键/值的选择器。我有一个内部 ID 和相应的 Show 值。 ID 并不总是具有 1、2、3 值,例如源自查找表,并且可能具有

KeyID / ShowValue
27 = Another Thing
55 = Many More
12 = Some Item

检索起来很简单

select * from LookupTable where Category = 'demo'

所以我在下面有这个类,用于通过记录列表绑定选择器

public class CboIntKeyValue
{
    public int KeyID { get; set; } = 0;
    public string ShowValue { get; set; } = "";
}

现在,我尝试绑定的数据记录只有与查找关联的 ID 列。无需陷入 xaml,但总的来说,我有我的 ViewModel。我有一个包含 ID 列的数据记录实例。

public class MyViewModel : BindableObject
{
    public MyViewModel()
    {
        // Sample to pre-load list of records from data server of KVP
        PickerChoices = GetDataFromServerForDemo( "select * from LookupTable where Category = 'demo'" );


        ShowThisRecord = new MyDataRec();
        // for grins, I am setting the value that SHOULD be defaulted 
        // in picker.  In this case, ID = 12 = "Some Item" from above
        ShowThisRecord.MyID = 12;   
    }

    // this is the record that has the "ID" column I am trying to bind to
    public MyDataRec ShowThisRecord {get; set;}

    // The picker is bound to this list of possible choices
    public List<CboIntKeyValue> PickerChoices {get; set;}
}

我无法绑定到列表的 INDEX,因为这会给我 0、1、2,而我希望相应的“ID”是列表中正确记录的基础。

在 WPF 中,我过去,能够为屏幕声明 SHOW 值,也可以将 BIND VALUE 与 ID 列类似。因此,我的“ShowThisRecord”上的 INT 属性绑定将驱动并正确刷新。

我可以看到 SelectedItem 的绑定,但这是 KVP 类的整个项目,它不是 MyDataRec 的一部分。只有 ID 是它们之间的共同元素。

谁能帮助指导我正确绑定以使其正常工作。

<Picker ItemDisplayBinding="{Binding ShowValue}" 
   SelectedItem="{Binding ???}" />

只是为了确认我的记录绑定是合法的,我的页面具有与 MyViewModel 的绑定上下文,因为我可以通过我添加到页面的示例文本条目正确地查看 ID。

<Entry Text="{Binding Path=ShowThisRecord.MyID}"/>

谢谢

【问题讨论】:

  • 我认为 SelectedItem 需要是在选择器的 ItemSource 中的一个项目

标签: c# xamarin data-binding picker


【解决方案1】:

我创建了一个演示来测试你的代码,它可以正常工作。完整的演示是here。我还添加了一个功能来验证所选项目。

如果你想同步获取SelectedItem对象,MyViewModel应该实现INotifyPropertyChanged,我为SelectedItem创建了一个selectedRecord字段,所以你可以这样做:

  public class MyViewModel :ViewModelBase
{
    public MyViewModel()
    {
        // Sample to pre-load list of records from data server of KVP
        //PickerChoices = GetDataFromServerForDemo("select * from LookupTable where Category = 'demo'");
       PickerChoices = new ObservableCollection<TestModel>() {
            new TestModel{ MyID = 5,ShowValue="test1" }, new TestModel{ MyID = 9,ShowValue="test2" },
            new TestModel{ MyID = 18,ShowValue="test18" }, new TestModel{ MyID = 34,ShowValue="test4" }
        };
       // set the default selected item 
       // foreach (TestModel model in PickerChoices) {
       //     if (model.MyID == 18) {// default value
       //         SelectedRecord = model;
       //         break;
       //     }
       // }


        ShowThisRecord = new TestModel();
        // for grins, I am setting the value that SHOULD be defaulted 
        // in picker.  In this case, ID = 12 = "Some Item" from above
        ShowThisRecord.MyID = 12;
    }

    // this is the record that has the "ID" column I am trying to bind to
    public TestModel ShowThisRecord { get; set; }

    //*****************************************

    TestModel selectedRecord; //selected item object
    public TestModel SelectedRecord
    {
        get { return selectedRecord; }
        set
        {
            if (selectedRecord != value)
            {
                selectedRecord = value;
                OnPropertyChanged();
            }
        }
    }

    //*****************************************

    // The picker is bound to this list of possible choices
    public ObservableCollection<TestModel> PickerChoices { get; set; }
}

班级ViewModelBase

 public  class ViewModelBase: INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

还有xaml

 <Picker  Title="Select a value" x:Name="mypicker"
    ItemsSource="{Binding Path= PickerChoices}"
    SelectedItem="{Binding SelectedRecord}"         
    ItemDisplayBinding="{Binding MyID}"/>

xaml.cs

 public partial class MainPage : ContentPage
{

    ObservableCollection<TestModel> items = new ObservableCollection<TestModel>();
    MyViewModel testModel = null;
    public MainPage()
    {
        InitializeComponent();

        testModel = new MyViewModel();
        BindingContext = testModel;

        //This will also work
        //if (testModel!=null && testModel.PickerChoices!=null) {
        //  for (int index=0;index< testModel.PickerChoices.Count;index++ ) {
        //        TestModel temp = testModel.PickerChoices[index];
        //    if (18 == temp.MyID) {
        //            mypicker.SelectedIndex = index;
        //            break;
        //     }
        //   }
        //}

        foreach (TestModel model in testModel.PickerChoices)
        {
            if (model.MyID == 18)
            {// default value
                testModel.SelectedRecord = model;
                break;
            }
        }
    }


    // to show the selected item
    private void Button_Clicked(object sender, EventArgs e)
    {
        if (testModel.SelectedRecord!=null) {
        DisplayAlert("Alert", "selected Item  MyID : " + testModel.SelectedRecord.MyID + "<--> ShowValue: " + testModel.SelectedRecord.ShowValue, "OK");
        }
    }

}

结果是:

【讨论】:

  • 欣赏报价,但我的问题是我想显示 SHOW 值,但让它返回整数键。
  • 没关系,不管是字符串还是整数,绑定都是一样的。将代码 ItemDisplayBinding="{Binding MyID}" 替换为 ItemDisplayBinding="{Binding ShowValue}"
  • 我已经更新了答案并发布了我测试的完整演示,你可以查看它。
  • 这看起来很有希望。我的问题的最后一部分是屏幕启动时默认显示。将您的 ID 值更改为非连续的,例如 5、9、18、34 并将默认值设置为 18。初始屏幕是否以 18 的“显示值”开始。最重要的是列表是与视图模型分开构建的,因此您不知道要直接使用的列表项。但由于记录来自已填充“ID”的表,因此我们知道该 ID 是正确的。非常感谢您为帮助我解决问题所做的努力。
  • 然后你可以先过滤数据列表。我已经更新了答案,你可以检查一下
【解决方案2】:

您需要将 ItemsSource 属性设置为您的 CboIntValue 项目列表:

<Picker Title="Select a value"
        ItemsSource="{Binding PickerChoices}"
        ItemDisplayBinding="{Binding ShowValue}" />

【讨论】:

  • 您需要设置 SelectedItem="{Binding ShowThisRecord.Value}" /> 但您不能使用 ID,因为它是一个 Picker,您需要绑定 String 值,所以首先在您的代码中做 ShowThisRecord.Value = PickerChoices.Single(p => p.Id == 12);
【解决方案3】:

经过大量工作,我最终为我需要的东西编写了自己的单独类和模板样式。做到这一点,并发布源代码供任何人使用、审查、评估等等,我将其发布在 CodeProject 上。

https://www.codeproject.com/Articles/5266341/Xamarin-Picker-with-ID-based-Binding

希望这可以帮助其他有类似问题的人。同样,我遇到的主要问题是,如果我有一个来自数据源的整数键 ID,则选择器不会仅通过给定的 ID(int 或字符串)自动刷新自身。

【讨论】:

    猜你喜欢
    • 2020-05-22
    • 2018-02-01
    • 2021-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-25
    • 1970-01-01
    • 2021-08-17
    相关资源
    最近更新 更多