使用Windows Phone在运行时加载xaml viewmodel

时间:2013-08-31 09:22:08

标签: c# xaml windows-phone-7 windows-phone-8 expression-blend

我目前正在关注Microsoft虚拟学院的Windows手机教程,其中一个挑战是使用在项目中创建并在运行时加载的设计xaml viewmodel。

经过几个小时的研究,我认为现在是时候采用stackoverflow了,因为我没有到达任何地方。我读了很多文章,没有人给我一个正确的答案,所以我有几个问题:

  1. 如何解决我的错误?
  2. 如何以编程方式在运行时加载xaml模型视图?
  3. 如何使用xaml?
  4. 在运行时加载xaml模型视图
  5. 在运行时调用xaml加载的位置
  6. 示例数据文件,即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.Markup.XamlParseException'发生在   System.Windows.ni.dll

         

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

         

    未知的解析器错误:扫描程序2147500037. [行:5位置:14]

    假设我可以解决此错误,这将解决我的问题1&amp; 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的,但大多数都与加载usercontrol等有关..但不是viewmodel

    非常感谢任何帮助。

    感谢。

2 个答案:

答案 0 :(得分:3)

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

xmlns:vm = "clr-namespace:SoundBoard.ViewModels;assembly=SoundBoard">

答案 1 :(得分: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所建议的。