3

我目前正在关注微软虚拟学院的 Windows Phone 教程,其中一个挑战是使用在项目中创建并在运行时加载的设计 xaml 视图模型。

在研究了几个小时之后,我认为是时候求助于 stackoverflow 了,因为我无处可去。我已经阅读了很多文章,但没有一篇文章给我正确的答案,所以我有几个问题:

  1. 如何解决我的错误?
  2. 如何以编程方式在运行时加载 xaml 模型视图?
  3. 如何使用 xaml 在运行时加载 xaml 模型视图?
  4. 在哪里调用运行时加载的 xaml

示例数据文件,即 SoundViewModelSampleData.xaml,如下所示:

<vm:SoundViewModel
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vm="clr-namespace:Soundboard.ViewModels"
    xmlns:mo="clr-namespace:Soundboard.Models">

    <vm:SoundViewModel.Animals>
        <vm:SoundGroupViewModel Title="Animals Sample">
            <vm:SoundGroupViewModel.Items>
                <mo:SoundDataModel Title="Animals 1" FilePath="Animals.wav" />
            </vm:SoundGroupViewModel.Items>
        </vm:SoundGroupViewModel>
    </vm:SoundViewModel.Animals>
    <vm:SoundViewModel.Cartoons>
        <vm:SoundGroupViewModel Title="Cartoons Sample">
            <vm:SoundGroupViewModel.Items>
                <mo:SoundDataModel Title="Cartoons 1" FilePath="Cartoons.wav" />
                <mo:SoundDataModel Title="Cartoons 2" FilePath="Cartoons.wav" />
            </vm:SoundGroupViewModel.Items>
        </vm:SoundGroupViewModel>
    </vm:SoundViewModel.Cartoons>
</vm:SoundViewModel>

我发现以编程方式加载它的最简单的代码是:

string path = @".\SampleData\SoundViewModelSampleData.xaml";
using (System.IO.StreamReader reader = new System.IO.StreamReader(path))
{
    SoundViewModel vm = XamlReader.Load(reader.ReadToEnd()) as SoundViewModel;
}

虽然我现在可能从错误的位置调用它,但我收到以下错误:

System.Windows.ni.dll 中出现“System.Windows.Markup.XamlParseException”类型的第一次机会异常

{System.Windows.Markup.XamlParseException:未知的解析器错误:扫描仪 2147500037。[行:5 位置:14] 在 MS.Internal.XcpImports.CreateFromXaml(字符串 xamlString,布尔 createNamescope,布尔 requireDefaultNamespace,布尔allowEventHandlers,布尔expandTemplatesDuringParse,布尔trimDeclaredEncoding ) 在 System.Windows.Markup.XamlReader.Load(String xaml) 在 Soundboard.ViewModels.SoundViewModel.LoadData()}

未知的解析器错误:扫描仪 2147500037。[行:5 位置:14]

假设我可以解决此错误,这将解决我的问题 1 和 2(修复错误并以编程方式加载数据)

你能找出导致这个问题的原因吗?

如上所述,当应用程序加载时创建它时,我可能将它加载到错误的位置,即从我的 ViewModel 中加载。

namespace Soundboard.ViewModels
{
    public class SoundViewModel
    {
        public SoundGroupViewModel Animals { get; set; }
        public SoundGroupViewModel Cartoons { get; set; }

        public bool IsDataLoaded { get; set; }

        public void LoadData()
        {
            string path = @".\SampleData\SoundViewModelSampleData.xaml";
            using (System.IO.StreamReader reader = new System.IO.StreamReader(path))
            {
                SoundViewModel vm = System.Windows.Markup.XamlReader.Load(reader.ReadToEnd()) as SoundViewModel;
        }
        IsDataLoaded = true;
    }
}

}

在我的 app.xaml.cs 我有以下内容:

public static SoundViewModel SoundViewModel
{
    get
    {
        if (_soundViewModel == null)
        {
            _soundViewModel = new SoundViewModel();
            _soundViewModel.LoadData();
        }

        return _soundViewModel;
    }
}

现在,我怎样才能在运行时仅使用 xaml 并在设计时使用 d:datacontext 来实现相同的效果。

我读过几篇文章,但它们都是针对 wpf 的,但大多数都与加载用户控件等有关。但不是视图模型

任何帮助将不胜感激。

谢谢。

4

2 回答 2

3

我正忙于与您的 XamlReader 类似的问题。我发现您应该在 xaml 文件的根元素中定义程序集命名空间,即使它包含在同一个程序集中。在下面的示例代码中,即使 xaml 包含在 SoundBoard.dll 中,我也会在 xaml 文件中声明其命名空间。

xmlns:vm = "clr-namespace:SoundBoard.ViewModels;assembly=SoundBoard">
于 2013-08-31T20:22:58.317 回答
1

也尝试过这样做,我能想到的最好的方法是将数据 XAML 文件移动到资产,将其标记为资源(我也删除了自定义工具),然后使用以下内容加载它:

    public void LoadData()
    {
        // Load data
        //LoadCodeData();
        LoadXamlData();

        IsDataLoaded = true;
    }

    private void LoadXamlData()
    {
        string path = "SoundBoard;component/assets/runtimecontent/SampleData.xaml";
        Uri uri = new Uri(path, UriKind.Relative);
        using (System.IO.StreamReader reader = new System.IO.StreamReader((System.Windows.Application.GetResourceStream(uri)).Stream))
        {
            SoundModel model = System.Windows.Markup.XamlReader.Load(reader.ReadToEnd()) as SoundModel;
            this.Animals = model.Animals;
            this.Cartoons = model.Cartoons;
            this.Taunts = model.Taunts;
            this.Warnings = model.Warnings;
            this.CustomSounds = model.CustomSounds;
        }
    }

我也按照 Bahti 的建议做了。

于 2013-09-01T07:44:41.733 回答