【问题标题】:Cannot assign void to an implicitly-typed local variable in WP 8.1无法将 void 分配给 WP 8.1 中的隐式类型局部变量
【发布时间】:2015-01-21 05:38:42
【问题描述】:

我正在 WP 8.1 中开发一个音乐播放器应用程序,我正在尝试在其中实现跳转列表功能。 为了实现跳转列表,我按照here给出的示例进行操作。

我正在对可用代码进行一些必要的更改,这就是我实现所需功能的方式,因为我对 C#、MVVM 和 WP 8.1 的了解很少。

但我的 ViewModel 在行中遇到错误

var items = ContactModel.CreateSampleData();

错误是:

Cannot assign void to an implicitly-typed local variable

可能的原因是什么????谁能帮我理解我哪里出错了。

using System.Collections;
using Windows.UI.Xaml.Data;
using JumpListSample.Common.JumpList;
using System.Collections.Generic;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using System;
using Windows.Storage;
using Windows.Storage.Search;
using System.Collections.ObjectModel;

namespace JumpListSample.ViewModels
{
    public class ContactsViewModel
    {
        private IList data;
        public IList Data
        {
            get
            {
                if (data == null)
                {
                    var items = ContactModel.CreateSampleData();
                    data = items.ToAlphaGroups(x => x.Name);
                }
                return data;
            }
        }
        private CollectionViewSource collection;

        public CollectionViewSource Collection
        {
            get
            {
                if (collection == null)
                {
                    collection = new CollectionViewSource();
                    collection.Source = Data;
                    collection.IsSourceGrouped = true;
                }
                return collection;
            }
        }
    }

    public class ContactModel
    {
        // constructor
        public ContactModel()
        {
            Name = "name";
            Albumart = new BitmapImage(new Uri("ms-appx:///Assets/Logo.scale-240.png"));
        }

        public async  static void CreateSampleData()
        {
            ObservableCollection<ContactModel> data = new ObservableCollection<ContactModel>();

            try
            {
                IReadOnlyList<IStorageItem> MusicLibrary = await KnownFolders.MusicLibrary.GetFoldersAsync(CommonFolderQuery.GroupByAlbum);
                foreach (IStorageItem item in MusicLibrary)
                {
                    ContactModel obj = new ContactModel();
                    IStorageItem musicItem = item;
                    obj.Name = musicItem.Name;
                    obj.Albumart = new BitmapImage(new Uri("ms-appx:///Assets/Logo.scale-240.png"));
                    data.Add(obj);
                }
            }
            catch
            {
            }
            finally
            {
            } 
        }

        public string Name { get; set; }
        public ImageSource Albumart { get; set; }
    }
}

演示代码可以从here下载。

【问题讨论】:

  • ContactModel.CreateSampleData() 不返回任何内容(从技术上讲,它返回 void),因此您不能将其分配给变量。您可能想要返回“数据”公共异步任务> CreateSampleData()。顺便说一句,一个空的“finally”语句是没有意义的
  • 我还应该补充一点,您必须“等待”结果。 IE。 var items = await ContactModel.CreateSampleData();
  • 老实说,我并没有深入研究所有这些的头部空间,但“项目”将是一个列表,因此您将返回“数据”。即整个列表

标签: c# mvvm windows-phone-8.1 jump-list


【解决方案1】:

我同意评论者克林特·古德的建议。您的 CreateSampleData() 方法似乎负责初始化 ContactModel 实例的集合。据推测,您是从 Data 属性调用它,因为这些是您要用于初始化 data 字段的项目。

也就是说,你有一个严重的问题:C# 属性不支持async/await 模式。解决此问题的一个习惯用法是异步初始化支持字段,然后在初始化完成时引发属性更改事件。不幸的是,您的 ContactsViewModel 类没有实现 INotifyPropertyChanged 或继承 DependencyObject(基于 XAML 的程序处理属性更改通知的两种方式)。

综合所有这些并对您的代码进行必要的更改,您最终会得到这样的结果:

ContactsViewModel:

public class ContactsViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }

    private IList data;
    public IList Data
    {
        get
        {
            if (data == null)
            {
                // Ignore the returned Task...we're not going to do anything with it
                var _ = InitData();
            }

            // Caller should handle null. If not, need to return "new Data[0]" here instead
            return data;
        }
    }

    private async Task InitData()
    {
        // Catch _specific_ exceptions here, if necessary

        var items = await ContactModel.CreateSampleData();
        data = items.ToAlphaGroups(x => x.Name);
        OnPropertyChanged("Data");
    }

    private CollectionViewSource collection;

    public CollectionViewSource Collection
    {
        get
        {
            if (collection == null)
            {
                collection = new CollectionViewSource();
                collection.Source = Data;
                collection.IsSourceGrouped = true;
            }
            return collection;
        }
    }
}

联系人模型:

public class ContactModel
{
    // constructor
    public ContactModel()
    {
        Name = "name";
        Albumart = new BitmapImage(new Uri("ms-appx:///Assets/Logo.scale-240.png"));
    }

    public async static Task<ObservableCollection<ContactModel>> CreateSampleData()
    {
        ObservableCollection<ContactModel> data = new ObservableCollection<ContactModel>();

        IReadOnlyList<IStorageItem> MusicLibrary = await KnownFolders.MusicLibrary.GetFoldersAsync(CommonFolderQuery.GroupByAlbum);
        foreach (IStorageItem item in MusicLibrary)
        {
            ContactModel obj = new ContactModel();
            IStorageItem musicItem = item;
            obj.Name = musicItem.Name;
            obj.Albumart = new BitmapImage(new Uri("ms-appx:///Assets/Logo.scale-240.png"));
            data.Add(obj);
        }

        return data;
    }

    public string Name { get; set; }
    public ImageSource Albumart { get; set; }
}

请注意,我还完全删除了您的 try/catch。简单地吞下异常是非常糟糕的。如果您认为需要处理任何异常,请在调用者(即ContactsViewModel.InitData())中处理它们,您可以在其中做一些有用的事情并在必要时通知用户(但只处理特定的异常,即您知道如何响应的异常)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-13
    • 2013-11-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多