为什么我对选择器的绑定不适用于 xaml/xamarin?

Why is my binding to my picker not working with xaml/xamarin?

XAML Xamarin 5 - MacOS

XAML:

<Picker x:Name="StylesPicker" Title="Select stylesheet" HorizontalOptions="FillAndExpand" SelectedIndexChanged="StylesPicker_SelectedIndexChanged" SelectedItem="{Binding Path=vrrData.Style, Mode=TwoWay}"/>

后面的代码:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AppKit;
using VisitsRota.ViewModels;
using Xamarin.Essentials;
using Xamarin.Forms;

namespace VisitsRota.Views
{
    public partial class ElderlyInfirmPage : ContentPage
    {
        public ObservableCollection<string> StylesList { get; set; }

        public ElderlyInfirmPage()
        {
            InitializeComponent();
            BindingContext = new ElderlyInfirmViewModel();

            string[] stylesArray = Directory.GetFiles("/Users/Shared/VisitsRota.MacOS/Styles", "ElderlyInfirm-Schedule-*.xsl")
                                      .Select(file => Path.GetFileName(file)).ToArray<string>();
            StylesList = new ObservableCollection<string>(stylesArray);
            StylesPicker.ItemsSource = StylesList;
     
        }    

        async private void InstallStyleButton_Clicked(object sender, EventArgs e)
        {
            var customFileType =
                new FilePickerFileType(new Dictionary<DevicePlatform, IEnumerable<string>>
                {
                    {DevicePlatform.macOS, new[] {"xsl"} }
                });

            var pickResult = await FilePicker.PickAsync(new PickOptions
            {
                FileTypes = customFileType,
                PickerTitle = "Select template to install"

            });

            if(pickResult != null)
            {
                StylesList.Add(pickResult.FileName);
            }
        }

        void StylesPicker_SelectedIndexChanged(System.Object sender, System.EventArgs e)
        {
            var picker = (Picker)sender;
            int selectedIndex = picker.SelectedIndex;

            if(selectedIndex != -1)
            {
                string x =   (string)picker.ItemsSource[selectedIndex];
            }
        }
    }
}

查看模型:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Xml.Serialization;

namespace VisitsRota.ViewModels
{
    public class ElderlyInfirmViewModel : BaseViewModel
    {
        public List<string> StylesList { get; set; }
        public List<string> ListMonths { get; }
        public VisitsRotaData vrrData { get; set; }

        public ElderlyInfirmViewModel()
        {
            vrrData = DeserializeFromXml<VisitsRotaData>("/Users/Shared/VisitsRota.MacOS/VisitsRotaData.xml");

            // Should this list be private?
            ListMonths = DateTimeFormatInfo.CurrentInfo.MonthNames.TakeWhile(m => m != String.Empty).ToList();

            StylesList = Directory.GetFiles("/Users/Shared/VisitsRota.MacOS/Styles", "ElderlyInfirm-Schedule-*.xsl")
                                      .Select(file => Path.GetFileName(file)).ToList<string>();

                
        }

        public T DeserializeFromXml<T>(string filePath)
        {
            try
            {
                if (!System.IO.File.Exists(filePath))
                    throw new ArgumentNullException(filePath + " not Exists");
                using (System.IO.StreamReader reader = new System.IO.StreamReader(filePath))
                {
                    System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(typeof(T));
                    T ret = (T)xs.Deserialize(reader);
                    return ret;
                }
            }
            catch (Exception ex)
            {
                return default(T);
            }
        }

    }
   
    [XmlType(TypeName="VisitsRotaData")]
    public class VisitsRotaData : BaseViewModel
    {

        private ObservableCollection<string> _listelders;
        private ObservableCollection<string> _listpublishers;
        private string _style;

        [XmlArray("Elders")]
        [XmlArrayItem("Elder")]
        public ObservableCollection<string> ListElders
        {
            get { return _listelders; }
            set {
                _listelders = value;
                OnPropertyChanged("ListElders");
            }
        }

        [XmlArray("Publishers")]
        [XmlArrayItem("Publisher")]
        public ObservableCollection<string> ListPublishers
        {
            get { return _listpublishers; }
            set
            {
                _listpublishers = value;
                OnPropertyChanged("ListPublishers");
            }
        }

        [XmlElement]
        public string Style
        {
            get { return _style; }
            set
            {
                _style = value;
                OnPropertyChanged("Style");
            }
        }
    }
}

XML数据:

<?xml version="1.0" encoding="UTF-8" ?>
<VisitsRotaData>
    <Elders>
        <Elder>Elder 1</Elder>
        <Elder>Elder 2</Elder>
        <Elder>Elder 3</Elder>
        <Elder>Elder 4</Elder>
        <Elder>Elder 5</Elder>
        <Elder>Elder 6</Elder>
        <Elder>Elder 7</Elder>
        <Elder>Elder 8</Elder>
    </Elders>
    <Publishers>
       <Publisher>Publisher 1</Publisher>
       <Publisher>Publisher 2</Publisher>
       <Publisher>Publisher 3</Publisher>
       <Publisher>Publisher 4</Publisher>
       <Publisher>Publisher 5</Publisher>
       <Publisher>Publisher 6</Publisher>
       <Publisher>Publisher 7</Publisher>
       <Publisher>Publisher 8</Publisher>
       <Publisher>Publisher 9</Publisher>
       <Publisher>Publisher 10</Publisher>
    </Publishers>
    <Style>ElderlyInfirm-Schedule-v2.xsl</Style>
</VisitsRotaData>

选择器使用文件夹中的文件进行填充。那也行。但是当 window 显示时,它选择了选择器中的第一项而不是第二项(这是样式的值。

预期行为:

将选择器的值绑定到样式 属性。 选择器默认为现有值。

看来我已经解决了。这个答案 here 为我指明了正确的方向。

XAML

我将 XAML 中的 Binding 更改为 Picker:

<Picker x:Name="StylesPicker" Title="Select stylesheet" 
        HorizontalOptions="FillAndExpand" 
        ItemsSource="{Binding StylesList}" 
        SelectedItem="{Binding Path=vrrData.Style, Mode=TwoWay}"/>

如您所见,我还删除了 StylesPicker_SelectedIndexChanged 处理程序。

代码隐藏

我从 class 中删除了 public ObservableCollection<string> StylesList { get; set; }

查看模型

我粘贴了前面提到的 StylesList 属性 并将其填充到 ElderlyInfirmViewModel 构造函数中。

Style 属性 保持不变 VisitsRotaData class.


样本

现在,当我的 window 显示时,Picker 默认为我的 XML 文件中的值:

我认为我在 代码后面 中使用 ItemSource 并且在 视图模型中使用 SelectedItem 使它复杂化。通过将其全部保存在一个位置(页面的 BindingContext),它可以工作。