XF UWP - MVVM - 如何在嵌套对象中绑定选择器选定的项目?
XF UWP - MVVM - How to bind Picker selected item in a Nested Object?
我无法更改基于 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;
}
*/
}
}
您应该在 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
,所以它有效。
我找到的解决方法是更改:
操作 class 到 :
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 ItemsSource="{Binding Path=BindingContext.model.SelectFromList,
Source={x:Reference MPage}}"
ItemDisplayBinding="{Binding name}"
Grid.Column="2"
SelectedItem="{Binding instance,Mode=TwoWay}"
>
</Picker>
我无法更改基于 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;
}
*/
}
}
您应该在 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
,所以它有效。
我找到的解决方法是更改:
操作 class 到 :
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 ItemsSource="{Binding Path=BindingContext.model.SelectFromList,
Source={x:Reference MPage}}"
ItemDisplayBinding="{Binding name}"
Grid.Column="2"
SelectedItem="{Binding instance,Mode=TwoWay}"
>
</Picker>