gpt4 book ai didi

windows-store-apps - 在 Windows 商店/wp reactiveui 应用程序中设置第一个 View /vm

转载 作者:行者123 更新时间:2023-12-04 07:57:05 26 4
gpt4 key购买 nike

我无法弄清楚如何使用 Reactive UI 正确导航到 Windows Store 8.1 应用程序中的第一个 View 。

在我的 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 View 。该 View 被声明为:
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 导航到新 View 。 :-) 我认为我应该使用 View 优先导航(来自我读过的其他内容)。

顺便说一句,我查看了文档(在 git repo 的文档分支中),恐怕我无法从那里弄清楚。此外,查看了“Playground...”应用程序,但它们没有构建(由于一些 pdb 冲突,当时没有推送,所以无法测试)。样本似乎也没有使用这个,新的样本 repo 看起来刚刚开始。另外,检查了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 文件使其在 ctor 中看起来像这样,它就可以工作:
    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 引用它。因此,对于一个成熟的应用程序,这条线可能是不必要的。

最后,我们需要主页面 View 模型:
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 支持绑定(bind)的设计时创作等,但我还没有解决这个问题。而且我不认为 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 在 View 模型上设置绑定(bind),在调用 ctor 时它实际上是 null。这是由管道处理的。与 MVVM 中的往常一样,View 了解所有关于 ViewModel 的信息,反之亦然。

最后是 StartPage View 模型:
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"; }
}
}

请注意最后两个属性,它们是可路由 View 接口(interface)依赖项所要求的。 HostScreen 需要由 ctor 设置,并且,正如您在 RxUI 应用程序中所期望的那样,您在 VM 的 ctor 中设置所有行为以进行行为。

我远不是这里的专家。如果有更简单的方法,请告诉我,我会尝试更新。或者删除一些样板代码的方法! :-)

关于windows-store-apps - 在 Windows 商店/wp reactiveui 应用程序中设置第一个 View /vm,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27612771/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com