在MvvmCross中拥有单个View/ViewModel/Xaml链接到多个Json资源文件的最佳方式

本文关键字:Json 资源 源文件 方式 最佳 链接 拥有 MvvmCross 单个 View Xaml | 更新日期: 2023-09-27 18:12:50

在我的应用程序中,我有许多帮助页面,它们都有类似的布局-头和正文。

我有它的结构的方式,目前,对于每一个帮助页我有一个视图,ViewModel, .xaml和.json文件。

问题是我的应用程序已经膨胀到我有大约20个帮助页面的程度,并且为每个帮助文件复制和粘贴这些页面显然效率低下且容易出错。我想要的是一个单一的HelpViewModel, HelpView, Page_Help.xml,然后为每个帮助页面一个不同的。json文件与相关的文本资源。

我不知道如何实现这一点,尽管通过查看现有的MvvmCross主题。

所以我的XAML的标题是这样的:
<TextView
  style="@style/HelpTextTitle"
  local:MvxBind="{'Text':'Path':'TextSource','Converter':'Language','ConverterParameter':'Heading1'}}"
/>

与ViewModel具有相同名称的json文件(并通过一些自动链接)看起来像这样:

{
  "Heading1":"Sample Help Heading",
}

我有一个HelpViewModel,可以接受一个参数-说json文件的名称

public string HeaderFile { get; private set; }
public HelpViewModel (string headerFile)
{
  HeaderFile = headerFile;
}

json文件目前与ViewModels相关联,我认为通过这个类:

public class TextProviderBuilder : MvxTextProviderBuilder
...
    protected override IDictionary<string, string> ResourceFiles
    {
        get
        {
            var dictionary = this.GetType()
                .Assembly
                .GetTypes()
                .Where(t => t.Name.EndsWith("ViewModel"))
                .Where(t => !t.Name.StartsWith("Base"))
                .ToDictionary(t => t.Name, t => t.Name);
            dictionary[Constants.Shared] = Constants.Shared;
            return dictionary;
        }
    }         

主应用程序将其注册为文本提供程序(因此我假设自动促进ViewModel-Json文件),如下所示:

var builder = new TextProviderBuilder();
this.RegisterServiceInstance<IMvxTextProvider>(builder.TextProvider);

所以很明显,在这里我想以某种方式使用相同的帮助页资源,但能够绑定该帮助页上的控件(最好)与参数(Header1)同名的不同json文件,或者必要时在单个json文件中使用不同的参数。

多谢!

马修


编辑:斯图尔特的解决方案下面工作完美。我只需要传递json文件的名称当我调用RequestNavigate这是通过ViewModel的构造函数:

return new MvxRelayCommand(() => this.RequestNavigate<GeneralHelpViewModel>(new { helpKey = "DescribeAudioCrimeStatementHelpViewModel" }));

我唯一要做的就是创建我自己的MvxLanguageBinder,因为在我的MvvmCross(不是最近的)的确切构建中,MvxLanguageBinder是私有的,不可访问。

我只是从Stuart的链接中复制并粘贴了版本,并使用了:

https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross.Localisation/MvxLanguageBinder.cs

在MvvmCross中拥有单个View/ViewModel/Xaml链接到多个Json资源文件的最佳方式

有几种方法可以达到这种效果。

如果你想继续使用单独的json文件,我可能会选择这样的方法…

将绑定更改为使用新的TextSource - CustomTextSource

<TextView
       style="@style/HelpTextTitle"
       local:MvxBind="{'Text':'Path':'CustomTextSource','Converter':'Language','ConverterParameter':'Heading1'}}"
 />

创建您的HelpViewModel,以便它使用导航参数加载此CustomTextSource:

 public HelpViewModel (string helpKey)
 {
       CustomTextSource = new MvxLanguageBinder(Constants.GeneralNamespace, helpKey);
 }
 public IMvxLanguageBinder CustomTextSource { get; private set; }

修改文本资源加载的代码,使其包含帮助文件。

protected override IDictionary<string, string> ResourceFiles
{
    get
    {
        var dictionary = this.GetType()
            .Assembly
            .GetTypes()
            .Where(t => t.Name.EndsWith("ViewModel"))
            .Where(t => !t.Name.StartsWith("Base"))
            .ToDictionary(t => t.Name, t => t.Name);
        dictionary[Constants.Shared] = Constants.Shared;
        foreach (var additional in HelpFileList)
        {
             dictionary(additional) = additional;
        } 
        return dictionary;
    }
}  

(我在这里假设HelpFileList是一个静态列表,但你也可以用反射来做到这一点。)


或者,如果你想把help json重新组织成一个文件,你也可以考虑写一个使用你的helpkey的自定义IMvxLanguageBinder。假设您使用的是vNext,那么MvxLanguageBinder的代码应该非常容易适应—来自axml的调用位于第58行


或者,如果这真的只是帮助文本,那么您可以考虑放弃这种xml和json方法-您可以使用嵌入的HTML来代替显示在web浏览器小部件中-这可能是最灵活的长期解决方案,可以允许最容易的内容更新在未来