将 xaml.cs 后面的代码移动到 xamarin 中的 ViewModel
Moving code behind xaml.cs to ViewModel in xamarin
我已经在 xaml.cs 文件中编写了我的后台代码逻辑,现在我想将我的代码从后台代码移动到 ViewModel。除了代码重构,如何做到这一点。
我是 xamarin 新手
这是我背后的代码
namespace _somename
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class CareingtonFeeSchedule : ContentPage
{
private OneDentalFeeScheduleService oneDentalFeeScheduleService;
private ObservableCollection<ProviderSearchViewModel> _allGroups;
private ObservableCollection<ProviderSearchViewModel> _expandedGroups;
protected ObservableCollection<Grouping<string, FeeScheduleItem>> feeScheduleGroups;
protected ObservableCollection<FeeScheduleItem> feeScheduleItems;
private readonly AppViewModel AppViewModelInstance;
private Plugin.Geolocator.Abstractions.Position currentPosition;
private FeeScheduleModel feeScheduleDataResult;
public CareingtonFeeSchedule(AppViewModel appViewModel)
{
InitializeComponent();
AppViewModelInstance = appViewModel;
BindingContext = AppViewModelInstance;
AppViewModelInstance.IsActivityLoading = true;
LoadFeeeSchedule();
}
private void HeaderTapped(object sender, EventArgs args)
{
int selectedIndex = _expandedGroups.IndexOf(
((ProviderSearchViewModel)((Button)sender).CommandParameter));
_allGroups[selectedIndex].Expanded = !_allGroups[selectedIndex].Expanded;
UpdateListContent();
}
async Task OnHomeFeeScheduleTapped_TappedAsync(object sender, EventArgs args)
{
await Navigation.PushAsync(new AccLandPage(AppViewModelInstance));
}
private void ProviderBar_TextChanged(object sender, TextChangedEventArgs e)
{
var keyword = ProviderSearchBar.Text;
GroupedView.ItemsSource =
_expandedGroups.Where(s =>
s.Title.ToLower().Contains(keyword.ToLower()));
}
private void UpdateListContent()
{
_expandedGroups = new ObservableCollection<ProviderSearchViewModel>();
foreach (ProviderSearchViewModel group in _allGroups)
{
ProviderSearchViewModel newGroup = new ProviderSearchViewModel(group.Title, group.ShortName, group.Expanded);
if (group.Expanded)
{
foreach (Plan plan in group)
{
newGroup.Add(plan);
}
}
_expandedGroups.Add(newGroup);
}
GroupedView.ItemsSource = _expandedGroups;
}
public FeeScheduleModel FeeScheduleDataResult
{
protected set
{
feeScheduleDataResult = value;
OnPropertyChanged(nameof(FeeScheduleDataResult));
}
get => feeScheduleDataResult;
}
protected int feeScheduleCount;
public int FeeScheduleCount => feeScheduleCount;
private async Task<bool> LoadFeeeSchedule()
{
try
{
if (oneDentalFeeScheduleService == null)
{
oneDentalFeeScheduleService = new OneDentalFeeScheduleService("1dental.com");
}
var feeSchedRes = await oneDentalFeeScheduleService.GetFeeScheduleAsync(AppViewModelInstance.ZipCode, string.Empty, CancellationToken.None);
if (feeSchedRes?.Schedule?.Count > 0)
{
ConvertFeeScheuleDict(feeSchedRes.Schedule);
}
else FeeScheduleDataResult = null;
return true;
}
catch (Exception eX)
{
with the fee schedule lookup: \n{eX.Message}", "OK");
return false;
}
finally
{
AppViewModelInstance.IsActivityLoading = false;
actInd.IsRunning = false;
}
}
private void ConvertFeeScheuleDict(Dictionary<string, List<FeeScheduleItem>> feesche)
{
ObservableCollection<ProviderSearchViewModel> list = new ObservableCollection<ProviderSearchViewModel>();
ProviderSearchViewModel psm = null;
foreach (var item in feesche)
{
psm = new ProviderSearchViewModel(item.Key, "");
foreach (var valitem in item.Value)
{
Plan p = new Plan();
p.Code = valitem.Code;
p.CostDisplay = valitem.CostDisplay;
p.Description = valitem.ProcedureSecondary;
p.Name = valitem.Procedure;
psm.Add(p);
}
list.Add(psm);
}
_allGroups = list;
UpdateListContent();
}
private async void GetZipCode()
{
try
{
if (AppViewModelInstance.UserPosition == null)
{
try
{
var hasPermission = await Utils.CheckPermissions(Permission.Location);
if (!hasPermission)
{
await Navigation.PushAsync(new MainScreen());
return;
}
}
catch (Exception ex)
{
Debug.WriteLine($"Exception occurred while looking permission during Appearing event: {ex}");
}
var locator = CrossGeolocator.Current;
currentPosition = await locator.GetPositionAsync(new TimeSpan(0, 0, 0, 10, 0));
var addressList = await locator.GetAddressesForPositionAsync(currentPosition, null);
AppViewModelInstance.UserPosition = currentPosition;
foreach (var item in addressList)
{
AppViewModelInstance.ZipCode = item.PostalCode;
ZipCodeEntry.Text = item.PostalCode;
break;
}
}
else
{
var locator = CrossGeolocator.Current;
currentPosition = AppViewModelInstance.UserPosition;
var addressList = await locator.GetAddressesForPositionAsync(currentPosition, null);
foreach (var item in addressList)
{
AppViewModelInstance.ZipCode = item.PostalCode;
ZipCodeEntry.Text = item.PostalCode;
break;
}
}
LoadFeeeSchedule();
}
catch (Exception ex)
{
Debug.WriteLine($"Exception occurred while looking up location during Appearing event: {ex}");
}
}
private void ZipCodeEntry_Complete(object sender, EventArgs e)
{
if (sender != null)
{
AppViewModelInstance.ZipCode = ((Entry)sender).Text;
}
}
private void ZipCodeEntry_Changed(object sender, EventArgs e)
{
if (sender != null)
{
string _text = ((Entry)sender).Text; //Get Current Text
if (_text.Length > 5) //If it is more than your character restriction
{
_text = _text.Remove(_text.Length - 1); // Remove Last character
ZipCodeEntry.Text = _text; //Set the Old value
}
if (_text.Length == 5)
{
AppViewModelInstance.ZipCode = _text;
LoadFeeeSchedule();
}
}
}
public bool CanRefreshExecute(string tempVal = null)
{
if (AppViewModelInstance.IsRefreshing) return false;
var valToCheck = tempVal ?? AppViewModelInstance.ZipCode;
if (string.IsNullOrEmpty(valToCheck) || string.IsNullOrWhiteSpace(valToCheck)) return false;
bool isDigitString = true;
foreach (var c in valToCheck)
{
if (char.IsDigit(c)) continue;
isDigitString = false;
}
if (isDigitString) AppViewModelInstance.ZipCode = valToCheck;
return isDigitString;
}
private void GroupedView_ItemTapped(object sender, ItemTappedEventArgs e)
{
}
}
}
只需将您的代码导出到视图模型并将视图模型设置为页面的绑定上下文。例如在构造函数中:
//In the code behind
PageViewModel viewModel;
public Page()
{
this.BindingContext = viewModel = new PageViewModel();
//...
}
ViewModel 应该实现 INotify属性Changed。
(由事件触发的函数必须留在代码后面并通过 ViewModel 访问视图模型属性)
我已经在 xaml.cs 文件中编写了我的后台代码逻辑,现在我想将我的代码从后台代码移动到 ViewModel。除了代码重构,如何做到这一点。
我是 xamarin 新手
这是我背后的代码
namespace _somename
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class CareingtonFeeSchedule : ContentPage
{
private OneDentalFeeScheduleService oneDentalFeeScheduleService;
private ObservableCollection<ProviderSearchViewModel> _allGroups;
private ObservableCollection<ProviderSearchViewModel> _expandedGroups;
protected ObservableCollection<Grouping<string, FeeScheduleItem>> feeScheduleGroups;
protected ObservableCollection<FeeScheduleItem> feeScheduleItems;
private readonly AppViewModel AppViewModelInstance;
private Plugin.Geolocator.Abstractions.Position currentPosition;
private FeeScheduleModel feeScheduleDataResult;
public CareingtonFeeSchedule(AppViewModel appViewModel)
{
InitializeComponent();
AppViewModelInstance = appViewModel;
BindingContext = AppViewModelInstance;
AppViewModelInstance.IsActivityLoading = true;
LoadFeeeSchedule();
}
private void HeaderTapped(object sender, EventArgs args)
{
int selectedIndex = _expandedGroups.IndexOf(
((ProviderSearchViewModel)((Button)sender).CommandParameter));
_allGroups[selectedIndex].Expanded = !_allGroups[selectedIndex].Expanded;
UpdateListContent();
}
async Task OnHomeFeeScheduleTapped_TappedAsync(object sender, EventArgs args)
{
await Navigation.PushAsync(new AccLandPage(AppViewModelInstance));
}
private void ProviderBar_TextChanged(object sender, TextChangedEventArgs e)
{
var keyword = ProviderSearchBar.Text;
GroupedView.ItemsSource =
_expandedGroups.Where(s =>
s.Title.ToLower().Contains(keyword.ToLower()));
}
private void UpdateListContent()
{
_expandedGroups = new ObservableCollection<ProviderSearchViewModel>();
foreach (ProviderSearchViewModel group in _allGroups)
{
ProviderSearchViewModel newGroup = new ProviderSearchViewModel(group.Title, group.ShortName, group.Expanded);
if (group.Expanded)
{
foreach (Plan plan in group)
{
newGroup.Add(plan);
}
}
_expandedGroups.Add(newGroup);
}
GroupedView.ItemsSource = _expandedGroups;
}
public FeeScheduleModel FeeScheduleDataResult
{
protected set
{
feeScheduleDataResult = value;
OnPropertyChanged(nameof(FeeScheduleDataResult));
}
get => feeScheduleDataResult;
}
protected int feeScheduleCount;
public int FeeScheduleCount => feeScheduleCount;
private async Task<bool> LoadFeeeSchedule()
{
try
{
if (oneDentalFeeScheduleService == null)
{
oneDentalFeeScheduleService = new OneDentalFeeScheduleService("1dental.com");
}
var feeSchedRes = await oneDentalFeeScheduleService.GetFeeScheduleAsync(AppViewModelInstance.ZipCode, string.Empty, CancellationToken.None);
if (feeSchedRes?.Schedule?.Count > 0)
{
ConvertFeeScheuleDict(feeSchedRes.Schedule);
}
else FeeScheduleDataResult = null;
return true;
}
catch (Exception eX)
{
with the fee schedule lookup: \n{eX.Message}", "OK");
return false;
}
finally
{
AppViewModelInstance.IsActivityLoading = false;
actInd.IsRunning = false;
}
}
private void ConvertFeeScheuleDict(Dictionary<string, List<FeeScheduleItem>> feesche)
{
ObservableCollection<ProviderSearchViewModel> list = new ObservableCollection<ProviderSearchViewModel>();
ProviderSearchViewModel psm = null;
foreach (var item in feesche)
{
psm = new ProviderSearchViewModel(item.Key, "");
foreach (var valitem in item.Value)
{
Plan p = new Plan();
p.Code = valitem.Code;
p.CostDisplay = valitem.CostDisplay;
p.Description = valitem.ProcedureSecondary;
p.Name = valitem.Procedure;
psm.Add(p);
}
list.Add(psm);
}
_allGroups = list;
UpdateListContent();
}
private async void GetZipCode()
{
try
{
if (AppViewModelInstance.UserPosition == null)
{
try
{
var hasPermission = await Utils.CheckPermissions(Permission.Location);
if (!hasPermission)
{
await Navigation.PushAsync(new MainScreen());
return;
}
}
catch (Exception ex)
{
Debug.WriteLine($"Exception occurred while looking permission during Appearing event: {ex}");
}
var locator = CrossGeolocator.Current;
currentPosition = await locator.GetPositionAsync(new TimeSpan(0, 0, 0, 10, 0));
var addressList = await locator.GetAddressesForPositionAsync(currentPosition, null);
AppViewModelInstance.UserPosition = currentPosition;
foreach (var item in addressList)
{
AppViewModelInstance.ZipCode = item.PostalCode;
ZipCodeEntry.Text = item.PostalCode;
break;
}
}
else
{
var locator = CrossGeolocator.Current;
currentPosition = AppViewModelInstance.UserPosition;
var addressList = await locator.GetAddressesForPositionAsync(currentPosition, null);
foreach (var item in addressList)
{
AppViewModelInstance.ZipCode = item.PostalCode;
ZipCodeEntry.Text = item.PostalCode;
break;
}
}
LoadFeeeSchedule();
}
catch (Exception ex)
{
Debug.WriteLine($"Exception occurred while looking up location during Appearing event: {ex}");
}
}
private void ZipCodeEntry_Complete(object sender, EventArgs e)
{
if (sender != null)
{
AppViewModelInstance.ZipCode = ((Entry)sender).Text;
}
}
private void ZipCodeEntry_Changed(object sender, EventArgs e)
{
if (sender != null)
{
string _text = ((Entry)sender).Text; //Get Current Text
if (_text.Length > 5) //If it is more than your character restriction
{
_text = _text.Remove(_text.Length - 1); // Remove Last character
ZipCodeEntry.Text = _text; //Set the Old value
}
if (_text.Length == 5)
{
AppViewModelInstance.ZipCode = _text;
LoadFeeeSchedule();
}
}
}
public bool CanRefreshExecute(string tempVal = null)
{
if (AppViewModelInstance.IsRefreshing) return false;
var valToCheck = tempVal ?? AppViewModelInstance.ZipCode;
if (string.IsNullOrEmpty(valToCheck) || string.IsNullOrWhiteSpace(valToCheck)) return false;
bool isDigitString = true;
foreach (var c in valToCheck)
{
if (char.IsDigit(c)) continue;
isDigitString = false;
}
if (isDigitString) AppViewModelInstance.ZipCode = valToCheck;
return isDigitString;
}
private void GroupedView_ItemTapped(object sender, ItemTappedEventArgs e)
{
}
}
}
只需将您的代码导出到视图模型并将视图模型设置为页面的绑定上下文。例如在构造函数中:
//In the code behind
PageViewModel viewModel;
public Page()
{
this.BindingContext = viewModel = new PageViewModel();
//...
}
ViewModel 应该实现 INotify属性Changed。
(由事件触发的函数必须留在代码后面并通过 ViewModel 访问视图模型属性)