Xamarin.formクロスプラットフォームアプリケーションに取り組んでいます。ボタンをクリックすると、あるページから別のページに移動できます。 Code-Behidファイルでのみ可能なため、ViewModelでNavigation.PushAsync(new Page2());
を実行できないため。これを行う方法を提案してください?
これが私の見解です:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.Microsoft.com/winfx/2009/xaml"
x:Class="Calculator.Views.SignIn"
xmlns:ViewModels="clr-namespace:Calculator.ViewModels;Assembly=Calculator">
<ContentPage.BindingContext>
<ViewModels:LocalAccountViewModel/>
</ContentPage.BindingContext>
<ContentPage.Content>
<StackLayout>
<Button Command="{Binding ContinueBtnClicked}"></Button>
</StackLayout>
</ContentPage.Content>
</ContentPage>
ここに私のViewModelがあります:
public class LocalAccountViewModel : INotifyPropertyChanged
{
public LocalAccountViewModel()
{
this.ContinueBtnClicked = new Command(GotoPage2);
}
public void GotoPage2()
{
/////
}
public ICommand ContinueBtnClicked
{
protected set;
get;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanges([CallerMemberName] string PropertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
}
}
1つの方法は、VMコンストラクターを介してナビゲーションを渡すことができます。ページはVisualElement
から継承するため、Navigation
プロパティを直接継承します。
コードビハインドファイル:
_public class SignIn : ContentPage
{
public SignIn(){
InitializeComponent();
// Note the VM constructor takes now a INavigation parameter
BindingContext = new LocalAccountViewModel(Navigation);
}
}
_
次に、VMでINavigation
プロパティを追加し、コンストラクターを変更してINavigation
を受け入れます。その後、ナビゲーションにこのプロパティを使用できます。
_public class LocalAccountViewModel : INotifyPropertyChanged
{
public INavigation Navigation { get; set;}
public LocalAccountViewModel(INavigation navigation)
{
this.Navigation = navigation;
this.ContinueBtnClicked = new Command(async () => await GotoPage2());
}
public async Task GotoPage2()
{
/////
await Navigation.PushAsync(new Page2());
}
...
_
修正する必要があるコードの問題に注意してください。GoToPage2()
メソッドをasync
に設定し、Task
型を返す必要があります。さらに、コマンドは非同期アクション呼び出しを実行します。これは、ページナビゲーションを非同期に行う必要があるためです!
それが役に立てば幸い!
簡単な方法は
this.ContinueBtnClicked = new Command(async()=>{
await Application.Current.MainPage.Navigation.PushAsync(new Page2());
});
VMから
public Command RegisterCommand
{
get
{
return new Command(async () =>
{
await Application.Current.MainPage.Navigation.PushAsync(new RegisterNewUser());
});
}
}
原則に基づいた私のアプローチは、すべてのビューがVMアプリのコンテキストベースの場所のみにナビゲートできる:
ViewModelでは、私はそのようなINavigationHandlerインターフェスを宣言します:
public class ItemsViewModel : ViewModelBase
{
public INavigationHandler NavigationHandler { private get; set; }
// some VM code here where in some place i'm invoking
RelayCommand<int> ItemSelectedCommand =>
new RelayCommand<int>((itemID) => { NavigationHandler.NavigateToItemDetail(itemID); });
public interface INavigationHandler
{
void NavigateToItemDetail(int itemID);
}
}
そして、ViewModelのINavigationHandlerとして分離コードクラスを割り当てます。
public class ItemsPage : ContentPage, ItemsViewModel.INavigationHandler
{
ItemsViewModel viewModel;
public ItemsPage()
{
viewModel = Container.Default.Get<ItemsViewModel>();
viewModel.NavigationHandler = this;
}
public async void NavigateToItemDetail(int itemID)
{
await Navigation.PushAsync(new ItemDetailPage(itemID));
}
}
私はこれを調べましたが、それはナビゲーションをどのように処理したいかによって異なります。ビューモデルでナビゲーションを処理するか、ビューを使用しますか。さまざまな状況やアプリケーションに合わせて異なるナビゲーション形式を選択できるように、ビューでナビゲーションを処理するのが最も簡単であることがわかりました。この状況では、コマンドバインディングモデルを使用するのではなく、ボタンクリックイベントを使用して、コードビハインドのナビゲーションスタックに新しいページを追加します。
ボタンを次のように変更します。
<StackLayout>
<Button Clicked="Button_Clicked"></Button>
</StackLayout>
そして、コードビハインドでメソッドを実装し、そこでナビゲーションを実行します。
public void Button_Clicked(object sender, EventArgs e)
{
Navigation.PushAsync(new Page2());
}
ビューモデルベースのナビゲーションを実行しようとしている場合、MvvmCrossでこれを行う方法はあると思いますが、そのツールには慣れていません。