MVVM ASYNC GUI SLQ连接

时间:2016-08-19 12:49:10

标签: c# wpf user-interface asynchronous mvvm

大家好(提前抱歉我是法国人), 我的代码有点问题。我尝试实现MVVM但我的ASYNC函数使我的程序错误,因为他打开我的连接异步,获取绑定对象列表(So null)并返回SQLReader但是为时已晚我的绑定不在GUI中刷新。我是MVVM系统的新手,所以我肯定会错过一些东西。

我的代码在这里(抱歉可以找到文字突出显示):

DataBinding XAML:

<UserControl.DataContext>
<local:UcGridViewModel/>
</UserControl.DataContext>

这里是ViewModel类:

    namespace *******.ViewModel
   {
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Data.SqlClient;
    using System.Linq;
    using Newtonsoft.Json;
    using DataObject;
    using DevExpress.Mvvm;

    public class UcGridViewModel : BindableBase
    {
        public UcGridViewModel()
        {
            this.InitaliseTreeViewDatacontext();
        }

        IEnumerable<TreeItem> treeItemDataBinding;
        public IEnumerable<TreeItem> TreeItemDataBinding
        {
            get
            {
               return this.GetProperty(()=> this.treeItemDataBinding);
            }
        }

        private async void InitaliseTreeViewDatacontext()
        {
            var listProprieteAscDesc = new ObservableCollection<Dictionary<string, string>>();
            var conn = DataAccess.GetSqlconnection();
            var jsonContextLocal = "\"*******\" : 2";
            jsonContextLocal += "\"*******\" : \"True\"";

            var sqlCmd = new SqlCommand("SELECT JSON FROM *******(" +
                        ApplicationContext.GetsimplifiedStringJsonContext(jsonContextLocal), conn);

            using (conn)
            {
                await conn.OpenAsync();


                var result = await sqlCmd.ExecuteReaderAsync();

                var pastFirstRow = false;
                while (await result.ReadAsync())
                {
                    if (!pastFirstRow)
                    {
                        pastFirstRow = true;
                        continue;
                    }

                    var json = result.GetString(0);

                    var deserializedObject = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
                    listProprieteAscDesc.Add(deserializedObject);
                }
            }

            this.treeItemDataBinding = listProprieteAscDesc.Select
                    (
                    d => new TreeItem(d["*******"], d["*******"], d["*******"])
                    );

        }
    }
    }

这是我的对象:

namespace *******.DataObject
{
    using DevExpress.Mvvm;

    public class TreeItem : BindableBase
    {
        public TreeItem(string label, string parent, string id)
        {
            this.Label = label;
            this.Parent = parent;
            this.Id = id;
        }

        public string Label
        {
            get
            {
                return this.GetProperty(() => this.Label);
            }
            private set
            {
                this.SetProperty(() => this.Label, value);
            }
        }

        public string Parent
        {
            get
            {
                return this.GetProperty(() => this.Parent);
            }
            private set
            {
                this.SetProperty(() => this.Parent, value);
            }
        }

        public string Id
        {
            get
            {
                return this.GetProperty(() => this.Id);
            }
            private set
            {
                this.SetProperty(() => this.Id, value);
            }
        }
    }
}

请有人能就我的问题向我提供一些提示,建议或解决方案吗?我希望(非常不是)很清楚。

提前谢谢。

1 个答案:

答案 0 :(得分:0)

如果我理解正确,目标是在用户控件启动时异步初始化VM中的数据。构造函数不能同步,因此您无法在其中进行异步调用。

解决此问题的一种方法是在VM中使用单独的InitializeAsync()函数并将其挂接到用户控件的Loaded事件。 VM部分看起来像这样:

public class MyViewModel 
{
   protected async Task InitializeAsync()
   {
       // Do async stuff here
   }
}

然后在用户控件的.cs中:

public partial class MyControl
{
    public MyControl()
    {
       Loaded += async (s, e) => await ((MyViewModel)DataContext).InitializeAsync();
    }
}

只要用户控件加载完其内容,就会异步加载数据。

编辑:您已经将Initialize功能分开,所以您只需将其公开并将其挂钩即可。 此外,您应该避免作为异步函数的返回类型的void。请改为使用任务here's why