为什么我对选择器的绑定不适用于 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),它可以工作。
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),它可以工作。