我无法确定如何使用Reactive UI正确导航到Windows应用商店8.1应用中的第一个视图。
在我的app.xaml.cs中,我有以下内容:
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
...
if (rootFrame.Content == null)
if (!rootFrame.Navigate(typeof(MainPage), e.Arguments))
{
throw new Exception("Failed to create initial page");
}
}
// Ensure the current window is active
Window.Current.Activate();
}
rootFrame.Navagate正确显示了我的MainPage.xaml视图。该视图声明为:
public sealed partial class MainPage : Page, IViewFor<MainPageViewModel>
{
public MainPage()
{
this.InitializeComponent();
RxApp.SuspensionHost.ObserveAppState<MainPageViewModel>()
.BindTo(this, x => x.ViewModel);
this.BindCommand(ViewModel, x => x.SwitchPages, x => x.FindIndicoUrl);
//this.NavigationCacheMode = NavigationCacheMode.Required;
}
但是,ViewModel未自动设置。我错过了什么代码?
接下来,我确定我还有另一个问题:如何从VM导航到新视图。 :-)我假设我应该使用查看第一个导航(来自我读过的其他内容)。
顺便说一下,我查看了文档(在git repo的docs分支中),我担心我无法从那里弄清楚。另外,看看&#34;游乐场......&#34;应用程序,但它们没有构建(由于某些pdb冲突,在那一点上没有推动,因此无法测试)。这些样品似乎也没有使用它,新的样品回购看起来似乎正在进行中。另外,检查SO。答案 0 :(得分:4)
在网上狩猎,以及SO(包括我11个月前提出的问题),我拼凑了一个答案,我在下面发帖。如果知道这些东西的人可以告诉我这是否正确,我会喜欢它。
首先,有关于此的文档:https://github.com/reactiveui/ReactiveUI/blob/master/docs/basics/routing.md。但是,对我来说,至少,它太高级了(例如,我没有在WPF世界中使用过RxUI)。但是现在我已经解决了这些问题,它确实有意义。
最后我的目标是看看我是否可以使用通用应用程序的通用代码。以下所有文件都是在共享项目中创建的。为Windows Store应用程序实现后退按钮等时,这可能会有所不同,但我还没有解决这个问题。
首先,您需要设置容器页面。我的MainPage.xaml的XAML如下所示:
<Page
x:Class="IWalker.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:IWalker"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:rxui="using:ReactiveUI"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<rxui:RoutedViewHost Router="{Binding Router}" />
</Grid>
主页面cs文件:
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
DataContext = Locator.Current.GetService(typeof(IScreen));
}
}
有很多方法可以设置数据上下文,我不确定最好的方法是什么...但只要你修改你的App.xaml.cs文件看起来像这样的东西就行了构造函数:
public App()
{
this.InitializeComponent();
this.Suspending += this.OnSuspending;
autoSuspendHelper = new AutoSuspendHelper(this);
RxApp.SuspensionHost.CreateNewAppState = () => new MainPageViewModel();
RxApp.SuspensionHost.SetupDefaultSuspendResume();
// Register everything... becasue....
Locator.CurrentMutable.Register(() => new StartPage(), typeof(IViewFor<StartPageViewModel>));
Locator.CurrentMutable.Register(() => new MeetingPage(), typeof(IViewFor<MeetingPageViewModel>));
// Create the main view model, and register that.
var r = new RoutingState();
Locator.CurrentMutable.RegisterConstant(r, typeof(RoutingState));
Locator.CurrentMutable.RegisterConstant(new MainPageViewModel(r), typeof(IScreen));
}
这里的关键是注释“//创建主视图模型”下面的行。你必须创建RoutingState,我可以在那里注册IScreen,以便稍后我可以选择它的单个版本。这是RxUI使用的所有DI代码。我不是100%确定我需要像这样注册的RoutingState,因为我总是最终在IScreen上引用它。所以可能是这条线是不必要的是一个完整的应用程序。
最后,我们需要主页面视图模型:
class MainPageViewModel : ReactiveObject, IScreen
{
/// <summary>
/// Return the routing state.
/// </summary>
public RoutingState Router { get; private set; }
public MainPageViewModel(RoutingState state = null)
{
Router = state;
// Go to the first page and get this show ion the road.
Router.Navigate.Execute(new StartPageViewModel(this));
}
}
在那里你看到路由器被存储,以及IScreen依赖。而且,最重要的是,您看到切换到StartPage,这是我的应用程序的第一个“有趣的页面”。
起始页非常简单。首先,请注意上面显示的App.xaml.cs ctor中的StartPage注册。接下来,这是xaml供参考:
<Page ...
<Grid>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBox Name="IndicoUrl" MinWidth="200"/>
<Button Name="FindIndicoUrl" Content="Load It!"/>
</StackPanel>
</Grid>
</Page>
接下来是xaml代码背后的代码。请注意,这不仅仅是其他一些框架(如CaliburnMicro)。很可能有更好的方法来做到这一点 - 我知道RxUI支持设计时间创作绑定等,但我还没有解决。我不认为RxUI按惯例实现了连接。
public sealed partial class StartPage : Page, IViewFor<StartPageViewModel>
{
public StartPage()
{
this.InitializeComponent();
this.BindCommand(ViewModel, x => x.SwitchPages, x => x.FindIndicoUrl);
this.Bind(ViewModel, x => x.MeetingAddress, y => y.IndicoUrl.Text);
}
public StartPageViewModel ViewModel
{
get { return (StartPageViewModel)GetValue(ViewModelProperty); }
set { SetValue(ViewModelProperty, value); }
}
public static readonly DependencyProperty ViewModelProperty =
DependencyProperty.Register("ViewModel", typeof(StartPageViewModel), typeof(StartPage), new PropertyMetadata(null));
object IViewFor.ViewModel
{
get { return ViewModel; }
set { ViewModel = (StartPageViewModel)value; }
}
}
请注意顶部的IVeiwFor依赖项。这需要稍微实现ViewModel依赖项属性。请注意,ctor在视图模型上设置绑定,在调用ctor时实际上为null。这是由管道处理的。像往常一样在MVVM中,View知道ViewModel的所有内容,反之亦然。
最后,StartPage视图模型:
public class StartPageViewModel : ReactiveObject, IRoutableViewModel
{
/// <summary>
/// When clicked, it will cause the page to switch and the text to be saved.
/// </summary>
public ReactiveCommand<object> SwitchPages { get; set; }
/// <summary>
/// The meeting address (bindable).
/// </summary>
public string MeetingAddress
{
get { return _meetingAddress; }
set { this.RaiseAndSetIfChanged(ref _meetingAddress, value); }
}
private string _meetingAddress;
/// <summary>
/// Setup the page
/// </summary>
public StartPageViewModel(IScreen screen)
{
HostScreen = screen;
// We can switch pages only when the user has written something into the meeting address text.
var canNavagateAway = this.WhenAny(x => x.MeetingAddress, x => !string.IsNullOrWhiteSpace(x.Value));
SwitchPages = ReactiveCommand.Create(canNavagateAway);
// When we navigate away, we should save the text and go
SwitchPages
.Select(x => MeetingAddress)
.Subscribe(addr =>
{
Settings.LastViewedMeeting = addr;
HostScreen.Router.Navigate.Execute(new MeetingPageViewModel(HostScreen, addr));
});
// Setup the first value for the last time we ran.
MeetingAddress = Settings.LastViewedMeeting;
}
/// <summary>
/// Track the home screen.
/// </summary>
public IScreen HostScreen {get; private set;}
/// <summary>
/// Where we will be located.
/// </summary>
public string UrlPathSegment
{
get { return "/home"; }
}
}
请注意最后两个属性,这些属性是可路由视图接口依赖项所要求的。 HostScreen需要由ctor设置,并且正如您在RxUI应用程序中所期望的那样,您可以在VM的ctor中设置所有行为。
我在这里远非专家。如果有更简单的方法,请告诉我,我会尝试更新此内容。或者删除一些样板代码的方法! : - )