【问题标题】:Bind data from async method从异步方法绑定数据
【发布时间】:2013-09-13 04:15:57
【问题描述】:

我仍在为我的项目而奋斗,我几乎不需要任何帮助。 在MainViewModel 中,我调用Refresh 方法将数据从XML 绑定到ObservableCollection。

private async Task Refresh()
    {
        var listOfBadges = (await _badgeService.GetAll());
        var listOfSets = (await _setService.GetAll());

        BadgesList.Clear();
        SetsList.Clear();

        BadgesList = listOfBadges.ToObservableCollection<Badge>();

        SetsList = listOfSets.ToObservableCollection<Set>();
    }

没关系 ;) 在QuestionViewModel 中,我正在使用 BadgeService 中的此方法编辑这些数据,该方法实现了存储库模式。

public async Task Update(int id)
    {
        StorageFolder sf = await ApplicationData.Current.LocalFolder.GetFolderAsync("Data");
        StorageFile st = await sf.GetFileAsync("Badgess.xml");

        var xmlStream = await FileIO.ReadTextAsync(st);

        XmlDocument xmlDoc = await XmlDocument.LoadFromFileAsync(st);

        using (var stream = await st.OpenAsync(FileAccessMode.ReadWrite))
        {
            XmlElement root = xmlDoc.DocumentElement;
            IXmlNode xee = root.SelectSingleNode("//badge/id[.='" + id + "']");
            xee.NextSibling.NextSibling.NextSibling.InnerText = "true";
        }

        var xmlStreamUp = xmlDoc.GetXml();

        if (xmlDoc != null)
            await xmlDoc.SaveToFileAsync(st);
    }

数据发生了变化,但是当我返回 MainViewModel 时,我无法看到绑定后的变化,但是当我点击绑定 Command 的按钮调用的 Refresh 方法时,会加载更改后的数据并且一切正常。 返回MainViewModel正确绑定数据后如何避免点击Refresh?

【问题讨论】:

  • 我想知道为什么您要手动操作 xml 而不是使用对象并定期将其保存到 xml 文件中。 xml 是否像某种数据库?
  • @Romoku 是的,它是一种数据库,我使用 XmlDocument 是因为我知道这在 Windows 应用商店应用程序中是一种很好的做法,我没有发现在 Windows 应用商店应用程序中使用 Linq2XML 示例。跨度>
  • Mml 对数据库不是很友好。您是否考虑过使用 sqlite?如果您已与 xml 结婚,请尝试将对象保存在内存中,而不是操作 xml 原始文件。这将不太容易出错,并且更容易更改 xml 格式。
  • 如果您有兴趣,这里有一个关于sqlite for windows phone 的好教程。

标签: c# data-binding mvvm async-await


【解决方案1】:

由于您的应用程序使用 xml 作为后备存储,请考虑将对象保留在内存中:

保存数据的存储库:

public interface IBadgeRepository
{
    // Save Xml File
    Task Save(IEnumerable<Badge> badges);
    // Load Xml File
    Task<Badge> GetAll();
}

操作数据的服务:

public sealed class BadgeService : IBadgeService
{
    private readonly IBadgeRepository _badgeRepository;
    private readonly List<Badge> _badges = new List<Badge>();

    public BadgeService(IBadgeRepository badgeRepository)
    {
        _badgeRepository = badgeRepository;
    }

    public async Task<IList<Badge>> GetAll()
    {
        if(!_badges.Any())
        {
            var badges = _badgeRepository.GetAll();
            _badges.AddRange(badges);
        }

        return Task.FromResult(_badge);
    }

    public async Task Update(Badge badge)
    {
        if(!_badges.Contains(badge))
        {
            _badges.Add(badge);
        }
        else
        {
            var index = _badges.IndexOf(badge);
            _badges[index] = badge;
        }

        _badgeRepository.Save(_badges);
    }
}

【讨论】:

  • 非常感谢,我会试试你说的更好的方法,但这个问题的答案如下。
【解决方案2】:

我发现问题的答案是调用 DialogService 以显示弹出窗口,更新 xml 并返回 MainViewModel

DialogService.ShowMessage("You should try another questions set!", "Game Over!", "Main Menu", GoToMainMenu);

它无法等待,所以我将其更改为:

await DialogService.ShowMessage("You should try another questions set!", "Game Over!");
await GoToMainMenu();

并以等待的方式从BadgeService 调用Update() 方法,如下所示:

private async Task GoToMainMenu()
    {
        await _badgeService.Update(SelectedSet.Id);
        ViewModelLocator.Cleanup();
        _navigationService.Navigate("MainPage");
    }

【讨论】:

    猜你喜欢
    • 2019-11-04
    • 2020-05-12
    • 1970-01-01
    • 2019-07-06
    • 2015-12-08
    • 1970-01-01
    • 1970-01-01
    • 2015-08-04
    • 1970-01-01
    相关资源
    最近更新 更多