Xamarin 选择器绑定
Xamarin Picker binding
我是不是遗漏了什么,或者还有什么我没有得到的?我正在开发一个移动应用程序,必须使用选择器从数据 table 中进行选择。首先,我有许多基于 key/value 的选择器。我有一个内部 ID 和相应的显示值。 ID 并不总是有 1、2、3 个值,例如源自查找 table,可能有
KeyID / ShowValue
27 = Another Thing
55 = Many More
12 = Some Item
检索简单如
select * from LookupTable where Category = 'demo'
所以我下面有这个 class 用于通过 list 记录
绑定选择器
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,因为当我期望相应的“ID”是列表中正确记录的基础。
在 WPF 中,我过去能够为屏幕声明 show 值,也可以声明 绑定值 类似于 ID 列。因此,在我的“ShowThisRecord”上绑定 INT 属性 将驱动并正确刷新。
我可以看到 SelectedItem 的绑定,但那是 KVP class 的整个项目,它是 MyDataRec 的 而不是 的一部分。只有ID是它们之间的共同元素。
什么是正确的绑定才能让它工作?
<Picker ItemDisplayBinding="{Binding ShowValue}"
SelectedItem="{Binding ???}" />
只是为了确认我的记录绑定是合法的,我的页面具有到 MyViewModel 的绑定上下文,因为我可以通过添加到页面的示例文本条目正确地看到 ID。
<Entry Text="{Binding Path=ShowThisRecord.MyID}"/>
您需要将 ItemsSource 属性 设置为您的 CboIntValue 项目列表:
<Picker Title="Select a value"
ItemsSource="{Binding PickerChoices}"
ItemDisplayBinding="{Binding ShowValue}" />
我创建了一个演示来测试您的代码,它运行正常。完整的演示是 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; }
}
class 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");
}
}
}
结果是:
经过大量工作,我最终编写了自己的单独 class 和模板样式来满足我的需要。由于它的篇幅,以及发布源代码供任何人使用、审查、评估等等,我把它发布了 on The Code Project。
同样,我遇到的主要问题是,如果我有一个来自数据源的整数键 ID,选择器将不会仅通过给定的 ID(整数或字符串)自动刷新自身。
我是不是遗漏了什么,或者还有什么我没有得到的?我正在开发一个移动应用程序,必须使用选择器从数据 table 中进行选择。首先,我有许多基于 key/value 的选择器。我有一个内部 ID 和相应的显示值。 ID 并不总是有 1、2、3 个值,例如源自查找 table,可能有
KeyID / ShowValue
27 = Another Thing
55 = Many More
12 = Some Item
检索简单如
select * from LookupTable where Category = 'demo'
所以我下面有这个 class 用于通过 list 记录
绑定选择器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,因为当我期望相应的“ID”是列表中正确记录的基础。
在 WPF 中,我过去能够为屏幕声明 show 值,也可以声明 绑定值 类似于 ID 列。因此,在我的“ShowThisRecord”上绑定 INT 属性 将驱动并正确刷新。
我可以看到 SelectedItem 的绑定,但那是 KVP class 的整个项目,它是 MyDataRec 的 而不是 的一部分。只有ID是它们之间的共同元素。
什么是正确的绑定才能让它工作?
<Picker ItemDisplayBinding="{Binding ShowValue}"
SelectedItem="{Binding ???}" />
只是为了确认我的记录绑定是合法的,我的页面具有到 MyViewModel 的绑定上下文,因为我可以通过添加到页面的示例文本条目正确地看到 ID。
<Entry Text="{Binding Path=ShowThisRecord.MyID}"/>
您需要将 ItemsSource 属性 设置为您的 CboIntValue 项目列表:
<Picker Title="Select a value"
ItemsSource="{Binding PickerChoices}"
ItemDisplayBinding="{Binding ShowValue}" />
我创建了一个演示来测试您的代码,它运行正常。完整的演示是 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; }
}
class 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");
}
}
}
结果是:
经过大量工作,我最终编写了自己的单独 class 和模板样式来满足我的需要。由于它的篇幅,以及发布源代码供任何人使用、审查、评估等等,我把它发布了 on The Code Project。
同样,我遇到的主要问题是,如果我有一个来自数据源的整数键 ID,选择器将不会仅通过给定的 ID(整数或字符串)自动刷新自身。