XF UWP - MVVM - 如何在嵌套对象中绑定选取器选定项?
Posted
技术标签:
【中文标题】XF UWP - MVVM - 如何在嵌套对象中绑定选取器选定项?【英文标题】:XF UWP - MVVM - How to bind Picker selected item in a Nested Object? 【发布时间】:2021-07-23 16:03:41 【问题描述】:我无法根据 Picker SelectedItem 更改对象,但我可以更改该对象的属性。我没看到什么?
我尝试将继承 ObservableCollections 的对象更改为将 ObservableCollections 作为属性并改为继承 PropertyChanged,但属性仍未注册更改。
XAML 绑定失败为空。
页面 XAML:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:viewmodel="clr-namespace:ItemSourceBug.ViewModel"
x:Class="ItemSourceBug.Views.MainPage"
x:Name="MPage">
<ContentPage.BindingContext>
<viewmodel:MainViewModel/>
</ContentPage.BindingContext>
<StackLayout BindableLayout.ItemsSource="Binding model.CurrentControlList"
VerticalOptions="Center">
<BindableLayout.ItemTemplate>
<DataTemplate>
<StackLayout BindableLayout.ItemsSource="Binding .">
<BindableLayout.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text="Binding typeAction"/>
<StackLayout BindableLayout.ItemsSource="Binding .">
<BindableLayout.ItemTemplate>
<DataTemplate>
<StackLayout Orientation="Horizontal">
<Label Text="Binding name"/>
<Label Text="Binding type"/>
<Picker ItemsSource="Binding Path=BindingContext.model.SelectFromList,
Source=x:Reference MPage"
ItemDisplayBinding="Binding name"
SelectedItem="Binding "> <!--This doesn't work-->
</Picker>
<Picker SelectedItem="Binding type"> <!--This works-->
<Picker.Items>
<x:String>3</x:String>
<x:String>4</x:String>
<x:String>5</x:String>
</Picker.Items>
</Picker>
<Label Text="Binding Path=BindingContext.model.currentAction.name, Source=x:Reference MPage"/>
<Picker ItemsSource="Binding Path=BindingContext.model.SelectFromList,
Source=x:Reference MPage"
ItemDisplayBinding="Binding name"
SelectedItem="Binding Path=BindingContext.model.currentAction, Source=x:Reference MPage"> <!--This works-->
</Picker>
</StackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</StackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</ContentPage>
页面视图模型:
using ItemSourceBug.Model;
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms;
namespace ItemSourceBug.ViewModel
public class MainViewModel : BaseViewModel
#region Properties
public MainModel model get; set; = new MainModel();
#endregion
#region Commands
#endregion
页面模型:
using ItemSourceBug.ViewModel;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text;
namespace ItemSourceBug.Model
public class MainModel: BaseViewModel
#region Properties
public ControlList CurrentControlList get; set; = new ControlList();
public Action currentAction get; set; = new Action id = "6", name = "Leon" ;
public Actions SelectFromList get; set; = new Actions();
#endregion
#region Constructor
public MainModel()
SelectFromList.Add(new Action id = "1239", name="George" );
SelectFromList.Add(new Action id = "1240", name = "Mike" );
#endregion
public class ControlList : ObservableCollection<TaskActions>
public string typeControl get; set;
public ControlList()
Add(new TaskActions typeTask = "observ" );
Add(new TaskActions typeTask = "discuss" );
public class TaskActions : ObservableCollection<Actions>
public string typeTask get; set;
public TaskActions()
Add(new Actions typeAction = "sing" );
Add(new Actions typeAction = "dance" );
public class Actions: ObservableCollection<Action>
public string typeAction get; set;
public Actions()
Add(new Action id = "1231" , name = "John" );
Add(new Action id = "1232", name = "Jane" );
Add(new Action id = "1237", name = "Joseph" );
Add(new Action id = "1238", name = "Jimbo" );
public class Action: BaseViewModel
public string id get; set;
public string name get; set;
public string type get; set; = "1";
/*
public override string ToString()
return name;
*/
【问题讨论】:
【参考方案1】:您应该在Label.Text
和Picker.SelectedItem + Picker.ItemDisplayBinding
上保持相同的绑定路径。
在您的代码中
第一个:
MPage.BindingContext.model.SelectFromList.name
!= model.CurrentControlList.x.x.name
,它们是不同的东西,所以它不起作用。
第二个:
type
= type
,所以它可以工作。
第三个:
MPage.BindingContext.model.currentAction.name
= MPage.BindingContext.model.currentAction.name
,所以它可以工作。
【讨论】:
首先...为什么这些对象不同?它们都是“动作”。我找到了一个解决方法,我会在一分钟内提出,但我想知道为什么它们不是要在 SelectedItem 上设置的相同对象?【参考方案2】:我发现的解决方法是改变:
动作类:
public class Action: INotifyPropertyChanged
public string id get; set;
public string name get; set;
public Action instance get; set;
public string type get; set; = "1";
/*
public override string ToString()
return name;
*/
//Reedited:
public Action()
instance = this;
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
var changed = PropertyChanged;
if (changed == null)
return;
if (propertyName.Equals("instance"))
name = instance.name;
id = instance.id;
type = instance.type;
changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
#endregion
我的 XAML 文件中的 Picker 为:
<Picker ItemsSource="Binding Path=BindingContext.model.SelectFromList,
Source=x:Reference MPage"
ItemDisplayBinding="Binding name"
Grid.Column="2"
SelectedItem="Binding instance,Mode=TwoWay"
>
</Picker>
【讨论】:
以上是关于XF UWP - MVVM - 如何在嵌套对象中绑定选取器选定项?的主要内容,如果未能解决你的问题,请参考以下文章
如何通过在 AngularJS 中绑定来捕获来自无效属性的 html 编译错误