I am stuck with a problem where I am checking network connectivity in an iOS app and trying to binding a boolean hasNetworkConnection in my view controller for it's view model.
View controller UpdateContentView.cs
// This file has been autogenerated from a class added in the UI designer.
using System;
using MvvmCross.iOS.Views;
using MvvmCross.Binding.BindingContext;
using Training.Core;
namespace EdwardsTraining.IOS
{
public partial class UpdateContentView : MvxViewController
{
public UpdateContentView(IntPtr handle) : base(handle)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
var bindingSet = this.CreateBindingSet<UpdateContentView, UpdateContentViewModel>();
bindingSet.Bind(NoConnectionView).For(x => x.Hidden).To(vm => vm.HasConnection).WithConversion("ReverseBoolean");
bindingSet.Bind(UpdateInProgressView).For(x => x.Hidden).To(vm => vm.InProgress).WithConversion("ReverseBoolean");
bindingSet.Bind(UpdateAvailableView).For(x => x.Hidden).To(vm => vm.HasContentUpdate).WithConversion("ReverseBoolean");
bindingSet.Bind(CancelButton).For(x => x.Hidden).To(vm => vm.CancelVisible).WithConversion("ReverseBoolean");
bindingSet.Bind(RetryButton).To(vm => vm.DoRetryUpdate);
bindingSet.Bind(ConfirmButton).To(vm => vm.DoUpdate);
//bindingSet.Bind(iOSNetworkConnectivitiy).For(x => x.HasNetworkConnection).To(vm => vm.NetworkConnectivitiy).TwoWay()
//.For(vm => vm.HasNetworkConnection);
bindingSet.Bind(iOSNetworkConnectivitiy).To(vm => vm.NetworkConnectivitiy).TwoWay();
bindingSet.Apply();
_iOSnetworkConnectivity = new NetworkConnectivity()
{
HasNetworkConnection = Reachability.IsNetworkAvailable()
};
}
private NetworkConnectivity _iOSnetworkConnectivity { get; set; }
public NetworkConnectivity iOSNetworkConnectivitiy {
get{return _iOSnetworkConnectivity;}
set { _iOSnetworkConnectivity = value;
}
}
}
}
I would like to check for connectivity using my iOS specific code and bind the boolean returned to a a public view model property.
View Model
using System;
using System.Threading.Tasks;
using EdwardsTraining.BusinessLayer.Interfaces.Services;
using MvvmCross.Core.ViewModels;
using MvvmCross.Platform;
namespace Training.Core
{
public class UpdateContentViewModel : BaseViewModel
{
private IApplicationContentService _applicationContentService;
private ITrainingContentService _trainingContentService;
public bool _isNetworkAvailable { get; set; }
public UpdateContentViewModel(IApplicationContentService applicationContentService, ITrainingContentService trainingContentService)
{
_applicationContentService = applicationContentService ?? Mvx.Resolve<IApplicationContentService>();
_trainingContentService = trainingContentService ?? Mvx.Resolve<ITrainingContentService>();
IntialSetup();
}
protected void IntialSetup()
{
_cancelVisible = false;
_hasContentUpdate = true;
_inProgress = false;
}
public void SetNoConnection()
{
_cancelVisible = true;
_hasContentUpdate = false;
_inProgress = false;
}
public void SetInProgress()
{
_cancelVisible = false;
HasContentUpdate = false;
InProgress = true;
}
public void SetProgessComplete()
{
InProgress = false;
Task.Run(async () => await FinishedUpdating());
}
public async Task UpdateContent()
{
if (_networkConnectivity.HasNetworkConnection)
{
SetInProgress();
await _trainingContentService.UpdateTrainingContentAsync();
await _applicationContentService.UpdateContent();
SetProgessComplete();
await FinishedUpdating();
}
return;
}
public async Task FinishedUpdating()
{
Close(this);
}
public MvxCommand DoUpdate
{
get { return new MvxCommand(async () => await UpdateContent()); }
}
public MvxCommand DoRetryUpdate
{
get { return new MvxCommand(async () => await UpdateContent()); }
}
public MvxCommand CancelUpdate
{
get { return new MvxCommand(async () => await FinishedUpdating()); }
}
private bool _hasContentUpdate;
public bool HasContentUpdate
{
get { return _hasContentUpdate; }
set
{
_hasContentUpdate = value;
RaisePropertyChanged(() => HasContentUpdate);
}
}
private bool _hasConnection;
public bool HasConnection
{
get { return _hasConnection; }
set
{
_hasConnection = value;
RaisePropertyChanged(() => HasConnection);
}
}
private bool _inProgress;
public bool InProgress
{
get { return _inProgress; }
set
{
_inProgress = value;
RaisePropertyChanged(() => InProgress);
}
}
private bool _cancelVisible;
public bool CancelVisible
{
get { return _cancelVisible; }
set
{
_cancelVisible = value;
RaisePropertyChanged(() => CancelVisible);
}
}
private NetworkConnectivity _networkConnectivity { get; set; }
public NetworkConnectivity NetworkConnectivitiy
{
get { return _networkConnectivity; }
set {
_networkConnectivity = value;
RaisePropertyChanged(() => NetworkConnectivitiy);
}
}
}
public class NetworkConnectivity
{
public bool HasNetworkConnection { get; set; }
}
}
I have a problem with this line of code:
public async Task UpdateContent()
{
if (_networkConnectivity.HasNetworkConnection)
{
SetInProgress();
await _trainingContentService.UpdateTrainingContentAsync();
await _applicationContentService.UpdateContent();
SetProgessComplete();
await FinishedUpdating();
}
return;
}
if (_networkConnectivity.HasNetworkConnection) is already null even though I set two way binding. I'm new to MVVM cross for this reason I don't know if my approach is correct.
Is there anyone who could provide some help?
Nick
You need to explicitly tell the binding what property you want to bind on your NetworkConnectivity like:
bindingSet.Bind(iOSNetworkConnectivitiy).For(v => v.HasNetworkConnection).To(vm => vm.NetworkConnectivitiy).TwoWay();
However, the binding does not have any way to get notified that your NetworkConnectivity class has gotten any of its values updated. Hence you would have to extend that class to have some kind of event where it can get notified.
Then, you would have to write and register a Target Binding class.
Lets say you simply implement INotifyPropertyChanged in your NetworkConnectivity class:
public class NetworkConnectivity : MvxNotifyPropertyChanged
{
private bool _hasNetworkConnection;
public bool HasNetworkConnection {
get { return _hasNetworkConnection; }
set {
_hasNetworkConnection = value;
RaisePropertyChanged();
}
}
}
Then you create the following class in your iOS project:
public class NetworkConnectivityTargetBinding
: MvxPropertyInfoTargetBinding<NetworkConnectivity>
{
public NetworkConnectivityTargetBinding(object target, PropertyInfo targetPropertyInfo)
: base(target, targetPropertyInfo)
{
var view = View;
if (view == null)
{
MvxBindingTrace.Trace(MvxTraceLevel.Error,
"NetworkConnectivity is null in NetworkConnectivityTargetBinding");
}
else
{
view.PropertyChanged += HandleValueChanged;
}
}
private void HandleValueChanged(object sender, System.EventArgs e)
{
var view = View;
if (view == null)
return;
FireValueChanged(view.HasNetworkConnection);
}
public override MvxBindingMode DefaultMode => MvxBindingMode.TwoWay;
protected override void Dispose(bool isDisposing)
{
if (isDisposing)
{
var view = View;
if (view != null)
{
view.PropertyChanged -= HandleValueChanged;
}
}
base.Dispose(isDisposing);
}
}
Then in Setup.cs override FillTargetFactories:
protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
registry.RegisterPropertyInfoBindingFactory(typeof(NetworkConnectivityTargetBinding),
typeof(NetworkConnectivity), "HasNetworkConnection");
base.FillTargetFactories(registry);
}
Now the TwoWay binding should work. You should also be able to remove the .For(v => v.HasNetworkConnection) from you binding expression.
Related
I have a view which opens an idialog that I contain a datagrid. I select certain rows and send back those as a list to the view but all I search I just found ResultButton return for idialog. How I can send back a custom value like a list or anything else ?
My iDialog ViewModel :
public DelegateCommand<string> CloseCommand { get; set; }
public DelegateCommand<string> AttachCommand { get; set; }
private string _txtSearch;
public string txtSearch
{
get { return _txtSearch; }
set { SetProperty(ref _txtSearch, value); }
}
public List<GE_Drawing> SelectedDrawings { get; set; }
private ObservableCollection<GE_Drawing> _DrawingList= new ObservableCollection<GE_Drawing>();
public ObservableCollection<GE_Drawing> DrawingList
{
get { return _DrawingList; }
set { SetProperty(ref _DrawingList, value); }
}
private bool _IsSelected;
public bool IsSelected
{
get { return _IsSelected; }
set { SetProperty(ref _IsSelected, value); }
}
public GE_DrawingAttachViewModel()
{
LoadList();
CloseCommand = new DelegateCommand<string>(onClose);
AttachCommand = new DelegateCommand<string>(onAttach);
}
private void onAttach(string parameter)
{
ButtonResult result = new ButtonResult();
var records = DrawingList.Where(x => x.IsSelected == true).ToList();
if(records.Count>0)
{
SelectedDrawings = records;
}
//result = ButtonResult.OK;
//RaiseRequestClose(new DialogResult(result));
}
private void RaiseRequestClose(DialogResult dialogResult)
{
RequestClose?.Invoke(dialogResult);
}
private void onClose(string parameter)
{
ButtonResult result = new ButtonResult();
result = ButtonResult.Cancel;
RaiseRequestClose(new DialogResult(result));
}
private string _title="Drawing List";
public string Title
{
get => _title;
set => SetProperty(ref _title, value);
}
public event Action<IDialogResult> RequestClose;
public bool CanCloseDialog()
{
return true;
}
public void OnDialogClosed()
{
}
public void OnDialogOpened(IDialogParameters parameters)
{
}
public async void LoadList()
{
GenericDataService<GE_Drawing> generic = new GenericDataService<GE_Drawing>();
DrawingList.AddRange(await generic.GetAll());
}
}
As written above I have an OnAttach which should send back my SelectedDrawings variable to the view but I dont know how to do that.
I have found the answer... IdialogResult have parameter with a value could be set to in dialog and get the value in the callback using a key.
private void openDialog()
{
DialogParameters parameter = new DialogParameters();
_dialogService.ShowDialog("GE_DrawingAttach", parameter, r =>
{
if(r.Result==ButtonResult.OK)
{
DrawingList = r.Parameters.GetValue<List<GE_Drawing>>("DrawingList");
}
});
}
How can I make sure that as soon as there is a change in the text field, the save button is enabled? or clicking edit (thus creating the button) the app enables editing and thus enabling the button,
and it has already been activated in case of insertion or deletion.
this a image of
app
Here is the code:
public GerenciarGenericoViewModel()
{
InserirProdutoCommand = new RelayCommand(InserirProduto);
ExcluirProdutoCommand = new RelayCommand(ExcluirProduto, CanExcluirProduto);
InserirUnidadeCommand = new RelayCommand(InserirUnidade);
ExcluirUnidadeCommand = new RelayCommand(ExcluirUnidade, CanExcluirUnidade);
InserirEmpresaCommand = new RelayCommand(InserirEmpresa);
ExcluirEmpresaCommand = new RelayCommand(ExcluirEmpresa, CanExcluirEmpresa);
InserirOperadorCommand = new RelayCommand(InserirOperador);
ExcluirOperadorCommand = new RelayCommand(ExcluirOperador, CanExcluirOperador);
SalvarCommand = new RelayCommand(Salvar, CanSalvar);
CancelarCommand = new RelayCommand(Cancelar);
ListaProdutos = new ObservableCollection<Produto>(ProdutosAccess.GetProdutos());
ListaUnidades = new ObservableCollection<UnidadeMedida>(ProdutosAccess.GetUnidadesMedida());
ListaEmpresas = new ObservableCollection<Empresa>(ProdutosAccess.GetEmpresas());
ListaOperadores = new ObservableCollection<Operador>(ProdutosAccess.GetOperadores());
}
public RelayCommand InserirProdutoCommand { get; }
public RelayCommand ExcluirProdutoCommand { get; }
public RelayCommand InserirUnidadeCommand { get; }
public RelayCommand ExcluirUnidadeCommand { get; }
public RelayCommand InserirEmpresaCommand { get; }
public RelayCommand ExcluirEmpresaCommand { get; }
public RelayCommand InserirOperadorCommand { get; }
public RelayCommand ExcluirOperadorCommand { get; }
int check = 0;
public RelayCommand SalvarCommand { get; }
public RelayCommand CancelarCommand { get; }
public ObservableCollection<Produto> ListaProdutos { get; }
public ObservableCollection<UnidadeMedida> ListaUnidades { get; }
public ObservableCollection<Empresa> ListaEmpresas { get; }
public ObservableCollection<Operador> ListaOperadores { get; }
private Produto _produtoSelecionado;
public Produto ProdutoSelecionado
{
get => _produtoSelecionado;
set => Set(() => ProdutoSelecionado, ref _produtoSelecionado, value);
}
private UnidadeMedida _unidadeSelecionada;
public UnidadeMedida UnidadeSelecionada
{
get => _unidadeSelecionada;
set => Set(() => UnidadeSelecionada, ref _unidadeSelecionada, value);
}
private Empresa _empresaSelecionada;
public Empresa EmpresaSelecionada
{
get => _empresaSelecionada;
set => Set(() => EmpresaSelecionada, ref _empresaSelecionada, value);
}
private Operador _operadorSelecionado;
public Operador OperadorSelecionado
{
get => _operadorSelecionado;
set => Set(() => OperadorSelecionado, ref _operadorSelecionado, value);
}
public void InserirProduto()
{
ListaProdutos.Add(new Produto());
check++;
}
public void ExcluirProduto()
{
ListaProdutos.Remove(ProdutoSelecionado);
check++;
}
public bool CanExcluirProduto()
{
return ProdutoSelecionado != null;
}
public void InserirUnidade()
{
ListaUnidades.Add(new UnidadeMedida());
check++;
}
public void ExcluirUnidade()
{
ListaUnidades.Remove(UnidadeSelecionada);
check++;
}
public bool CanExcluirUnidade()
{
return UnidadeSelecionada != null;
}
public void InserirEmpresa()
{
ListaEmpresas.Add(new Empresa());
check++;
}
public void ExcluirEmpresa()
{
ListaEmpresas.Remove(EmpresaSelecionada);
check++;
}
public bool CanExcluirEmpresa()
{
return EmpresaSelecionada != null;
}
public void InserirOperador()
{
ListaOperadores.Add(new Operador());
check++;
}
public void ExcluirOperador()
{
ListaOperadores.Remove(OperadorSelecionado);
check++;
}
public bool CanExcluirOperador()
{
return OperadorSelecionado != null;
}
public void Salvar()
{
var listaProdutos = ListaProdutos.ToList();
var listaUnidades = ListaUnidades.ToList();
var listaEmpresas = ListaEmpresas.ToList();
var listaOperadores = ListaOperadores.ToList();
listaProdutos = listaProdutos.Where(x => !string.IsNullOrWhiteSpace(x.Descricao)).ToList();
listaUnidades = listaUnidades.Where(x => !string.IsNullOrWhiteSpace(x.Descricao)).ToList();
listaEmpresas = listaEmpresas.Where(x => !string.IsNullOrWhiteSpace(x.Descricao)).ToList();
listaOperadores = listaOperadores.Where(x => !string.IsNullOrWhiteSpace(x.Nome)).ToList();
ProdutosAccess.SetListProdutos(listaProdutos);
ProdutosAccess.SetListUnidades(listaUnidades);
ProdutosAccess.SetListEmpresas(listaEmpresas);
ProdutosAccess.SetListOperadores(listaOperadores);
MessageBox.Show(messageBoxText: "Dados salvos com sucesso!",
caption: "Gerenciar Dados", button: MessageBoxButton.OK,
icon: MessageBoxImage.Information);
Sair();
}
public bool CanSalvar()
{
if (check == 0)
{
return false;
}
else
{
return true;
}
}
public void Cancelar()
{
Sair();
}
public void Sair()
{
Navigator.CloseWindowByDataContext(this);
}
}
As #BradleDotNET mentioned just set the UpdateSourceTrigger inside your TextBox Text binding to PropertyChanged and it should work.
I am trying to implement a searchbar using MVVM in Xamarin.forms. so far I have managed to borrow some code from around the internet and it seems to do go through the motions of the search. the only issue is I don't know what code to put in the command.
I would like the search bar to search recipeNames from a list of Recipes. this information is all stored on a local database and displayed using an observable collection.
please can you help me work it out.
XAML
<SearchBar x:Name="SearchBar"
Placeholder="Search"
SearchCommand="{Binding SearchCommand}"
SearchCommandParameter="{Binding Text, Source={x:Reference SearchBar}}"
Text="{Binding SearchText, Mode=TwoWay}">
<SearchBar.Behaviors>
<local:TextChangedBehavior />
</SearchBar.Behaviors>
</SearchBar>
<ListView x:Name="ListViewItems"
ItemsSource="{Binding Recipes}"
IsPullToRefreshEnabled="True"
Refreshing="ListViewItems_Refreshing"
SelectedItem="{Binding SelectedRecipe}">
Text changed Behaviour
class TextChangedBehavior: Behavior<Xamarin.Forms.SearchBar>
{
protected override void OnAttachedTo(Xamarin.Forms.SearchBar bindable)
{
base.OnAttachedTo(bindable);
bindable.TextChanged += Bindable_TextChanged;
}
protected override void OnDetachingFrom(Xamarin.Forms.SearchBar bindable)
{
base.OnDetachingFrom(bindable);
bindable.TextChanged -= Bindable_TextChanged;
}
private void Bindable_TextChanged(object sender, TextChangedEventArgs e)
{
((Xamarin.Forms.SearchBar)sender).SearchCommand?.Execute(e.NewTextValue);
}
}
and viewModel
public class RecipeListViewModel : ObservableCollection<Recipe>
{
private ObservableCollection<Recipe> Recipes {get; set;}
public INavigation Navigation { get; internal set; }
public ICommand NewAddPage { get; protected set; }
public RecipeListViewModel(INavigation navigation)
{
this.Navigation = navigation;
Recipes = new ObservableCollection<Recipe>();
this.NewAddPage = new Command(async () => await CreateNewAddPage());
Init();
}
// Gets all recipes from the database and adds them to the observable collection
private void Init()
{
var enumarator = App.RecipeDbcontroller.GetRecipe();
if (enumarator == null)
{
App.RecipeDbcontroller.SaveRecipe(new Recipe { RecipeName = "Moussaka", Serves = 6, PrepTime = "30", CookTime = "2 Hours", MealType = "Dinner" });
enumarator = App.RecipeDbcontroller.GetRecipe();
}
while (enumarator.MoveNext())
{
//cleans database of all empty records
if (enumarator.Current.RecipeName == null || enumarator.Current.CookTime == null)
{
App.RecipeDbcontroller.DeleteRecipe(enumarator.Current.RecipeID);
}
else
Add(enumarator.Current);
}
}
private ICommand _searchCommand;
public ICommand SearchCommand
{
get
{
return _searchCommand ?? (_searchCommand = new Command<string>((text) =>
{
**// THIS IS WHAT I DON'T KNOW WHAT TO DO**
}));
}
}
private string _searchText { get; set; }
public string SearchText
{
get { return _searchText; }
set
{
if (_searchText != value)
{
_searchText = value;
}
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
RecipeDatabaseController Class
public RecipeDatabaseController()
{
this.database = DependencyService.Get<ISQLite>().GetConnection();
this.database.CreateTable<Recipe>();
}
//Recipe CRUD
public IEnumerator<Recipe> GetRecipe()
{
lock (locker)
{
if (database.Table<Recipe>().Count() == 0)
{
return null;
}
else
{
return this.database.Table<Recipe>().GetEnumerator();
}
}
}
public IEnumerator<Recipe> GetRecipeBySearchTerm(text)
{
var enumarator = GetRecipe();
lock (locker)
{
while (enumarator.MoveNext)
{
if(enumarator.Current.RecipeName.Contains(text)
return this.
}
}
}
public int SaveRecipe(Recipe recipe)
{
lock (locker)
{
if (recipe.RecipeID != 0)
{
this.database.Update(recipe);
return recipe.RecipeID;
}
else
{
return this.database.Insert(recipe);
}
}
}
public int DeleteRecipe(int Id)
{
lock (locker)
{
return this.database.Delete<Recipe>(Id);
}
}
right so the search command ought to look like this.
public ICommand SearchCommand => _searchCommand ?? (_searchCommand = new Command<string>((text) =>
{
if (text.Length >=1)
{
Recipes.Clear();
Init();
var suggestions = Recipes.Where(c => c.RecipeName.ToLower().StartsWith(text.ToLower())).ToList();
Recipes.Clear();
foreach (var recipe in suggestions)
Recipes.Add(recipe);
}
else
{
Recipes.Clear();
Init();
ListViewVisible = true;
SuggestionsListViewVisible = false;
}
}));
using System.Linq;
//Recipe CRUD
public IEnumerable<Recipe> GetRecipe()
{
lock (locker)
{
return this.database.Table<Recipe>();
}
}
public IEnumerable<Recipe> GetRecipeBySearchTerm(string text)
{
var recipes = GetRecipe();
lock (locker)
{
return recipes.Where(m => m.RecipeName.ToLower().Contains(text));
}
}
Add the using System.Linq reference
Change those two methods and return IEnumerable
Note. RecipeName is the property you want to filter your Recipe with.
And your search command as below
private ICommand _searchCommand;
public ICommand SearchCommand
{
get
{
return _searchCommand ?? (_searchCommand = new Command<string>((text) =>
{
var filteredRecipes = App.RecipeDbcontroller.GetRecipeBySearchTerm(text);
recipes.Clear();
foreach(var recipe in filteredRecipes )
recipes.Add(recipe);
}));
}
}
I have not tested this code, so not sure where I might get errors, but you can work out the rest because the logic is given to you
Good luck
Im using the MVVMCross 4.4.0 and my FirstView is a List View like WhatsApp. When I click an item, my SecondView is a common view with just a field to update a property and change my FirstView, but this is not happen.
My First View Code
public sealed partial class MyOrdersView : MvxViewController
{
UITableView tableView;
public MyOrdersView() : base("MyOrdersView", null)
{
}
public override void DidReceiveMemoryWarning()
{
base.DidReceiveMemoryWarning();
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
tableView = new UITableView
{
Frame = new CoreGraphics.CGRect(0, 0, View.Bounds.Width, View.Bounds.Height),
CellLayoutMarginsFollowReadableWidth = true,
};
Add(tableView);
var tableSource = new MvxSimpleTableViewSource(tableView, OrderCell.Key, OrderCell.Key);
tableView.Source = tableSource;
var set = this.CreateBindingSet<MyOrdersView, Core.ViewModels.MyOrdersViewModel>();
set.Bind(tableSource).To(vm => vm.Tasks);
set.Bind(tableSource).For(s => s.SelectionChangedCommand).To(vm => vm.ItemSelectedCommand);
set.Apply();
tableView.ReloadData();
Title = "Meus Pedidos";
AppDelegate app = UIApplication.SharedApplication.Delegate as AppDelegate;
NavigationItem.SetLeftBarButtonItem(
new UIBarButtonItem(UIImage.FromBundle("threelines")
, UIBarButtonItemStyle.Plain
, (sender, args) => app.SidebarController.ToggleMenu()), true);
}
}
And ViewModel
public class MyOrdersViewModel : BaseViewModel
{
private IOrderService orderService;
public ObservableCollection<ValOrders2TO> tasks;
private MvxCommand<ValOrders2TO> _itemSelectedCommand;
public MyOrdersViewModel(IOrderService orderService)
{
this.orderService = orderService;
tasks = orderService.getAvailableOrders();
searchMyOrders();
}
private async Task<bool> searchMyOrders()
{
orderService.clearAvailableOrders();
orderService.addAllAvailableOrders(await orderService.searchMyOrders());
return true;
}
public ObservableCollection<ValOrders2TO> Tasks
{
get { return tasks; }
set { tasks = value; RaisePropertyChanged(() => Tasks); }
}
public ICommand ItemSelectedCommand
{
get
{
_itemSelectedCommand = _itemSelectedCommand ?? new MvxCommand<ValOrders2TO>(DoSelectItem);
return _itemSelectedCommand;
}
}
private void DoSelectItem(ValOrders2TO item)
{
ShowViewModel<MyOrdersDetailModel>(new { idOrder = item.id });
}
}
My Second View Code
public sealed partial class MyOrdersDetailView : MvxViewController<MyOrdersDetailModel>
{
public MyOrdersDetailView() : base("MyOrdersDetailView", null)
{
//ViewDidLoad();
}
public override void DidReceiveMemoryWarning()
{
base.DidReceiveMemoryWarning();
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
var btnBack = UIButton.FromType(UIButtonType.System);
btnBack.Frame = new CGRect(2, 35, 50, 20);
btnBack.SetTitle("Voltar", UIControlState.Normal);
Add(btnBack);
var set = this.CreateBindingSet<MyOrdersDetailView, Core.ViewModels.MyOrdersDetailModel>();
set.Bind(txtItemDes).To(vm => vm.txtItemDes);
set.Bind(btnUpdate).To(vm => vm.update);
set.Apply();
}
}
And the ViewModel
public class MyOrdersDetailModel : MvxViewModel
{
public ValOrders2TO _valItem;
public INC<string> txtItemDes = new NC<string>();
public MyOrdersDetailModel(IMessageService messageService, IOrderService orderService)
{
}
public ValOrders2TO Item
{
get { return _valItem; }
set { _valItem = value; RaisePropertyChanged(() => Item); }
}
public void Init(ValOrders2TO item)
{
Item = item;
ConfigProp();
}
void ConfigProp()
{
txtItemDes.Value = Item.itemsDes;
}
public IMvxCommand Update
{
get
{
return new MvxCommand(() => updateOrder());
}
}
private bool updateOrder()
{
Item.itemsDes = txtItemDes.Value;
return true;
}
public IMvxCommand CloseCommand
{
get { return new MvxCommand(() => Close(this)); }
}
}
This is my Bean Code
public class ValOrders2TO
{
//[JsonProperty()]
public int id { get; set; }
//[JsonProperty()]
public string itemsDes { get; set; }
}
And this is my OrderCell
public partial class OrderCell : MvxTableViewCell
{
public static readonly UINib Nib = UINib.FromName("OrderCell", NSBundle.MainBundle);
public static readonly NSString Key = new NSString("OrderCell");
private readonly MvxImageViewLoader _loader;
public OrderCell(IntPtr handle) : base(handle)
{
this.DelayBind(() =>
{
var set = this.CreateBindingSet<OrderCell, Core.ValOrders2TO>();
set.Bind(lblItemDes).To(item => item.itemsDes);
set.Apply();
});
}
public static OrderCell Create()
{
return (OrderCell)Nib.Instantiate(null, null)[0];
}
}
I know how to remove the items from my ListView like this:
orderService.deleteAvailableOrder(Item);
But I don't know how to update the items list.
Following attached my print screens
Try to implement RaisePropertyChanged for
public string itemsDes { get; set; }
I have a MvxDialogFragment and I want to show that using ViewModel, similarly when a activity is showed from ViewModel using ShowViewModel. Is it possible? How can I do that?
This is my scenario: I have a page that contains a MvxListView and, when the user click in a listview item, I want to show a MvxDialogFragment.
My ListView layout:
<Mvx.MvxListView
android:id="#+id/lstViewTasks"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:dividerHeight="1px"
android:clickable="true"
android:focusableInTouchMode="true"
android:choiceMode="multipleChoice"
android:layout_alignParentTop="true"
local:MvxBind="ItemsSource Tasks; ItemClick ItemClickCommand"
local:MvxItemTemplate="#layout/projectmytasksitem" />
My ListView ViewModel:
public class ProjectMyTasksViewModel : MvxViewModel
{
#region [Atributos privados]
private ProjectService _service;
#endregion
#region [Propriedades]
private IList<Task> _tasks;
public IList<Task> Tasks
{
get { return _tasks; }
set { _tasks = value; RaisePropertyChanged(() => Tasks); }
}
private bool _isListaVazia;
public bool IsListaVazia
{
get { return _isListaVazia; }
set { _isListaVazia = value; RaisePropertyChanged(() => IsListaVazia); }
}
private Task _selectedTask;
public Task SelectedTask
{
get { return _selectedTask; }
set { _selectedTask = value; RaisePropertyChanged(() => SelectedTask); }
}
private string _mensagemErro;
public string MensagemErro
{
get { return _mensagemErro; }
set { _mensagemErro = value; RaisePropertyChanged(() => MensagemErro); }
}
#endregion
#region [Commands]
private IMvxCommand _itenClickCommand;
public IMvxCommand ItemClickCommand
{
get
{
this._itenClickCommand = this._itenClickCommand ?? new MvxCommand<Task>(this.ExecuteItemClickCommand);
return _itenClickCommand;
}
}
#endregion
#region [Construtores]
public ProjectMyTasksViewModel()
{
_service = new ProjectService();
this.CriaListaTeste();
IsListaVazia = (Tasks.Count > 0) ? true : false;
}
#endregion
#region [Execuções dos Comandos]
private void ExecuteItemClickCommand(Task task)
{
Dictionary<string, Task> parametros = new Dictionary<string, Task>()
{
{"Task", task }
};
this.ShowViewModel<TaskViewModel>(parametros);
}
#endregion
#region [Métodos]
public void CriaListaTeste()
{
Tasks = new List<Task>();
for (int indiceProjeto = 1; indiceProjeto <= 10; indiceProjeto++)
{
Tasks.Add(new Task { Name = $"Tarefa {indiceProjeto}", StartDate = DateTime.Now, FinishDate = DateTime.Now, IsCompleted = false });
}
}
#endregion
}
My Listview Activity:
[Activity(Label = "My Task",
ConfigurationChanges = ConfigChanges.Orientation,
ScreenOrientation = ScreenOrientation.Portrait)]
public class ProjectMyTasksView : MvxActivity
{
public new ProjectMyTasksViewModel viewModel
{
get { return (ProjectMyTasksViewModel)base.ViewModel; }
set { base.ViewModel = value; }
}
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
this.SetContentView(Resource.Layout.ProjectMyTasksView);
}
}
My Dialog Fragment:
public class ProjectMyTaskDialog : MvxDialogFragment<TaskViewModel>
{
public override Dialog OnCreateDialog(Bundle savedState)
{
base.EnsureBindingContextSet(savedState);
this.BindingInflate(Resource.Layout.ProjectMyTasksDialog, null);
return base.OnCreateDialog(savedState);
}
}
My Dialog Fragment ViewModel:
public class TaskViewModel : BaseViewModel<TaskService, Task>
{
#region [Atributos Privados]
private readonly IMvxPictureChooserTask _pictureChooserTask;
#endregion
#region [Commands]
private MvxCommand _chooseImageCommand;
public MvxCommand ChooseImageCommand
{
get
{
_chooseImageCommand = _chooseImageCommand ?? new MvxCommand(ExecuteChooseImageCommand);
return _chooseImageCommand;
}
}
private MvxCommand _takePictureCommand;
public MvxCommand TakePictureCommand
{
get
{
_takePictureCommand = _takePictureCommand ?? new MvxCommand(ExecuteTakePictureCommand);
return _takePictureCommand;
}
}
private MvxCommand _completeTaskCommand;
public MvxCommand CompleteTaskCommand
{
get
{
_completeTaskCommand = _completeTaskCommand ?? new MvxCommand(ExecuteCompleteTaskCommand);
return _completeTaskCommand;
}
}
#endregion
#region [Construtores]
public TaskViewModel(IMvxPictureChooserTask pictureChooserTask)
{
_pictureChooserTask = pictureChooserTask;
}
#endregion
#region [Execuções dos Comandos]
private void ExecuteChooseImageCommand()
{
_pictureChooserTask.ChoosePictureFromLibrary(400, 95, OnImage, () => { });
}
private void ExecuteTakePictureCommand()
{
_pictureChooserTask.TakePicture(400, 95, OnImage, () => { });
}
public void ExecuteCompleteTaskCommand()
{
throw new NotImplementedException();
}
#endregion
#region [Métodos]
public void Init(Dictionary<string, Task> parametros)
{
Objeto = parametros["Task"];
}
private void OnImage(Stream imageStream)
{
var memoryStream = new MemoryStream();
imageStream.CopyTo(memoryStream);
Objeto.Image = memoryStream.ToArray();
}
#endregion
public class Parametros
{
public string TaskJson { get; set; }
}
}
There is no presenter for DialogFragments.
Instead you could have instantiate the Command from the Activity or have a callback into the Activity which determines what to do when the command is called, i.e. displaying the Dialog.
So for a simple example:
public class MyViewModel : MvxViewModel
{
public Action ShowTaskCommandAction {get;set;}
private MvxCommand _showTaskCommand;
public ICommand ShowTaskCommand =>
_showTaskCommand = _showTaskCommand ?? (_showTaskCommand = new MvxCommand(DoShowTaskCommand));
private void DoShowTaskCommand()
{
CommandAction?.Invoke();
// do other stuff here...
}
}
Then in your Activity or Fragment:
public class MyActivity : MvxActivity<MyViewModel>
{
public void OnCreate(Bundle _)
{
base.OnCreate(_);
ViewModel.ShowTaskCommandAction = () => {
var dialogFragment = new ProjectMyTaskDialog() {
DataContext = task
});
dialogFragment.Show(FragmentManager);
};
// whatever else code
}
}