简体   繁体   English

XF UWP - MVVM - 如何在嵌套的 Object 中绑定选取器选定项?

[英]XF UWP - MVVM - How to bind Picker selected item in a Nested Object?

I'm unable to change an object based on Picker SelectedItem, but I can change a property of that object.我无法根据 Picker SelectedItem 更改 object,但我可以更改 object 的属性。 What am I not seeing?我没看到什么?

I have tried changing object that inherit ObservableCollections to have ObservableCollections as properties and inherit PropertyChanged instead, but property it's still not registering a change.我尝试将继承 ObservableCollections 的 object 更改为将 ObservableCollections 作为属性并继承 PropertyChanged,但属性它仍然没有注册更改。

XAML Binding Failures is empty. XAML 绑定失败为空。

Page 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>

Page ViewModel:页面视图模型:

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
    }
}

Page Model:页 Model:

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;
        }
        */
    }
}

You should keep the same binding path on Label.Text and Picker.SelectedItem + Picker.ItemDisplayBinding .您应该在Label.TextPicker.SelectedItem + Picker.ItemDisplayBinding上保持相同的绑定路径。

In your code在您的代码中

First one:第一:

MPage.BindingContext.model.SelectFromList.name != model.CurrentControlList.xxname , they are different things, so it does not work. MPage.BindingContext.model.SelectFromList.name != model.CurrentControlList.xxname ,它们是不同的东西,所以它不起作用。


Second one:第二个:

type = type , so it works. type = type ,所以它有效。


Third one:第三个:

MPage.BindingContext.model.currentAction.name = MPage.BindingContext.model.currentAction.name , so it works. MPage.BindingContext.model.currentAction.name = MPage.BindingContext.model.currentAction.name ,所以它工作。

The workaround I found was to change:我发现的解决方法是更改:

Action class to:行动 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
    }

And the Picker in my XAML file to:我的 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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM