【发布时间】:2015-09-01 00:11:09
【问题描述】:
Hy
我想分享我在使用 MVVM-Light 的 Xamarin PCL 项目中自定义 xamarin.forms 控件的方法。你怎么看?
自定义控件 -> PersonPanel.xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="xxx.PersonPanel">
<StackLayout Orientation="Vertical">
<Label x:Name="titleLabel" Text="{Binding TitleLabel}"/>
<Entry x:Name="filterText" Placeholder="{Binding FilterPlaceholderText}" Text="{Binding Filter.Lookup}" TextChanged="OnFilterTextChanged"/>
<Label x:Name="resultText" Text="{Binding ResultText}" IsVisible="{Binding ResultTextVisible}"/>
</StackLayout>
</ContentView>
代码隐藏 -> PersonPanel.xaml.cs:
public partial class PersonPanel : ContentView
{
public PersonPanel()
{
InitializeComponent();
//Init ViewModel
BindingContext = ServiceLocator.Current.GetInstance<PersonPanelViewModel>();
}
private PersonPanelViewModel PersonPanelViewModel
{
get
{
return (PersonPanelViewModel)BindingContext;
}
}
public string TitleLabel
{
get
{
return PersonPanelViewModel.TitleLabel;
}
set
{
PersonPanelViewModel.TitleLabel = value;
}
}
public string FilterPlaceholderText
{
get
{
return PersonPanelViewModel.FilterPlaceholderText;
}
set
{
PersonPanelViewModel.FilterPlaceholderText = value;
}
}
private void OnFilterTextChanged(object sender, EventArgs e)
{
PersonPanelViewModel.SearchCommand.Execute(null);
}
}
ViewModel -> PersonPanelViewModel:
public class PersonPanelViewModel : ViewModelBase
{
private IPersonService _personService;
private decimal _personId = 0;
private string _titleLabel = string.Empty;
private string _filterPlaceholderText = string.Empty;
private string _resultText = string.Empty;
private bool _resultTextVisible = true;
public PersonPanelViewModel(IPersonService personService)
{
_personService = personService;
// Init Filter
Filter = new PersonFilter();
// Init Commands
SearchCommand = new RelayCommand(Search);
}
public ICommand SearchCommand { get; set; }
public PersonFilter Filter
{
get;
private set;
}
public string ResultText
{
get
{
return _resultText;
}
set
{
Set(() => ResultText, ref _resultText, value);
}
}
public bool ResultTextVisible
{
get
{
return _resultTextVisible;
}
set
{
Set(() => ResultTextVisible, ref _resultTextVisible, value);
}
}
public string FilterPlaceholderText
{
get
{
return _filterPlaceholderText;
}
set
{
Set(() => FilterPlaceholderText, ref _filterPlaceholderText, value);
}
}
public string TitleLabel
{
get
{
return _titleLabel;
}
set
{
Set(() => TitleLabel, ref _titleLabel, value);
}
}
public decimal PersonId
{
get
{
return _PersonId;
}
set
{
Set(() => PersonId, ref _PersonId, value);
}
}
private async void Search()
{
//Reset
ResultText = string.Empty;
ResultTextVisible = false;
PersonId = 0;
if (Filter.PersonLookup != null && Filter.PersonLookup.Length >= 3)
{
//Call to Person Service
List<PersonResult> Person = await _personService.FindpersonByFilter(Filter);
if (Person.Count == 1)
{
PersonId = Person[0].PersonId;
ResultText = Person[0].PersonName;
ResultTextVisible = true;
}
}
}
}
在另一个视图中使用控件:
<?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:components="clr-namespace:xxx.ViewElements.Components"
x:Class="xxx.MainPage">
<StackLayout Orientation="Vertical">
<components:PersonPanel x:Name="personPanel" TitleLabel="Person" FilterPlaceholderText="Type your search criteria here..."/>
</StackLayout>
</ContentPage>
我使用 Autofac 作为 IOC 容器。
你怎么看?我以正确的方式使用 MVVM(这对我来说很新)?
有没有更好的方法来处理从视图上的事件(TextChanged)调用命令?
Code-Behind(执行到 ViewModel 的路由)中的属性是什么?
编辑: 我将尝试描述我想要实现的目标:
- 创建我们自己的控件(可在不同视图中重复使用,跨平台)-> PersonPanel.xaml
- 在我们的 PCL 项目中用 XAML 编写,其中包含纯 Xamarin.Forms 控件
- 控件应该有它自己的命令(搜索)和属性
- 其中一个命令是使用服务
- 控件应该通过 IOC 获得服务(作为接口)注入
- 服务本身也在 PCL 项目中实现,并对 Web 服务进行 REST 调用
- 调用结果设置为控件的属性 -> ResultText 属性
- 结果对用户可见
-> 有了上面的实现,所有这些都可以,但我不确定这是否是正确的方法......
感谢您的帮助!
亲切的问候, 彼得
【问题讨论】:
标签: xamarin mvvm-light xamarin.forms portable-class-library