【问题标题】:Property set inside async callback not staying set在异步回调中设置的属性未保持设置
【发布时间】:2011-01-06 14:54:49
【问题描述】:

所以我遇到了一个奇怪的错误,希望有人能帮助我。

我有以下代码从 WCF RIA 服务中获取一些实体,这是在 Silverlight 4 中,但我猜这并没有什么区别。

我错过了什么?

public class MyModel
{
    ...

    public IEnumerable<MyEntity> Result { get; private set; }

    public void Execute()
    {
        Context.Load(Query, LoadBehavior.RefreshCurrent, o =>
        {
            if (o.HasError)
            {
                ExecuteException = o.Error;
                if (ExecuteError != null)
                    ExecuteError(this, EventArgs.Empty);
                o.MarkErrorAsHandled();
            }
            else
            {
                //I've stepped through the code and the assignment is working
                //Result != null
                Result = o.Entities; 
                if (ExecuteSuccess != null)
                    ExecuteSuccess(this, EventArgs.Empty);
                //Inside any Handler of ExecuteSuccess
                //MyModel.Result == null
                //However I set a break point after ExecuteSuccess is triggered,
                //and once again MyModel.Result != null

            }

            if (ExecuteComplete != null)
                ExecuteComplete(this, EventArgs.Empty);

            ExecuteBusy = false;

        }, false);
    }
}

一切正常,直到我到达这一点:

MyModel.ExecuteSuccess += (o,e) => {
    //At this point MyModel.Result == null.  but why?
    var result = MyModel.Result;
};

【问题讨论】:

  • 为什么不更改 ExecuteSuccess 以便您可以将 o.Entities 传递给 EventArgs?
  • 这适用于这种情况,但我认为绑定到MyModel.Result
  • 不确定这是否可行。你可以试试(o as MyModel).Result 吗?
  • @decyclone:我发现了问题,这是一个铸造问题,你的评论给了我这个想法,但它在我的代码的不同部分。谢谢!

标签: c# wcf silverlight-4.0 asynchronous


【解决方案1】:

是的,我发现我正在做一些疯狂的事情以使 MVVM + RIA 服务更有趣的问题,在一个继承类中我将 MyModel.Result 转换为 MyModel.Result as IEnumerable&lt;TEntity&gt;; 这不起作用。我改用MyModel.Result.OfType&lt;TEntity&gt;。我发布所有代码以防对其他人有用。

public abstract class RiaQuery : INotifyPropertyChanged
{
    #region INotifyPropertyChanged values

    public event PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    #endregion

    #region Query

    private EntityQuery _Query;

    public EntityQuery Query
    {
        get { return _Query; }
        private set
        {
            if (_Query != value)
            {
                _Query = value;
                RaisePropertyChanged("Query");
            }
        }
    }

    #endregion

    #region Result

    private IEnumerable _Result;

    public IEnumerable Result
    {
        get { return _Result; }
        private set
        {
            if (_Result != value)
            {
                _Result = value;
                RaisePropertyChanged("Result");
            }
        }
    }

    #endregion

    #region ExecuteBusy

    private bool _ExecuteBusy;

    public bool ExecuteBusy
    {
        get { return _ExecuteBusy; }
        private set
        {
            if (_ExecuteBusy != value)
            {
                _ExecuteBusy = value;
                RaisePropertyChanged("ExecuteBusy");
            }
        }
    }

    #endregion

    #region ExecuteCommand

    private DelegateCommand _ExecuteCommand;

    public DelegateCommand ExecuteCommand
    {
        get
        {
            if (_ExecuteCommand == null)
            {
                _ExecuteCommand = new DelegateCommand(o => Execute(o), o => !ExecuteBusy);
            }
            return _ExecuteCommand;
        }
    }

    #endregion

    #region ExecuteException

    private Exception _ExecuteException;

    public Exception ExecuteException
    {
        get { return _ExecuteException; }
        private set
        {
            if (_ExecuteException != value)
            {
                _ExecuteException = value;
                RaisePropertyChanged("ExecuteException");
            }
        }
    }

    #endregion

    public event EventHandler ExecuteBegin;
    public event EventHandler ExecuteComplete;
    public event EventHandler ExecuteSuccess;
    public event EventHandler ExecuteError;

    protected  DomainContext Context;

    public bool CreateQueryEachTime { get; set; }

    public RiaQuery(DomainContext context)
    {
        if (context == null) throw new ArgumentException("context");
        Context = context;
    }

    public void Execute(object param)
    {
        ExecuteBusy = true;

        if (ExecuteBegin != null)
            ExecuteBegin(this, EventArgs.Empty);

        if (CreateQueryEachTime || Query == null)
            CreateQueryInternal();

        Context.Load(Query, LoadBehavior.RefreshCurrent, o =>
        {
            if (o.HasError)
            {
                ExecuteException = o.Error;
                if (ExecuteError != null)
                    ExecuteError(this, EventArgs.Empty);
                o.MarkErrorAsHandled();
            }
            else
            {
                Result = o.Entities;
                if (ExecuteSuccess != null)
                    ExecuteSuccess(this, EventArgs.Empty);
            }

            if (ExecuteComplete != null)
                ExecuteComplete(this, EventArgs.Empty);

            ExecuteBusy = false;

        }, false);
    }

    private void CreateQueryInternal()
    {
        Query = CreateQuery();
    }

    protected abstract EntityQuery CreateQuery();
}

public abstract class RiaQuery<TContext> : RiaQuery
    where TContext : DomainContext
{
    new protected TContext Context
    {
        get { return base.Context as TContext; }
        set { base.Context = value; }
    }

    public RiaQuery(TContext context) : base(context) { }
}

public abstract class RiaQuery<TContext,TEntity> : RiaQuery<TContext>
    where TContext : DomainContext
    where TEntity : Entity 
{
    new public EntityQuery<TEntity> Query
    {
        get { return base.Query as EntityQuery<TEntity>; }
    }

    new public IEnumerable<TEntity> Result
    {
        get { return base.Result.OfType<TEntity>(); }
    }

    public RiaQuery(TContext context) : base(context) { }
}

public class DelegateRiaQuery<TContext> : RiaQuery<TContext>
    where TContext : DomainContext
{
    protected Func<TContext, EntityQuery> CreateQueryDelegate;

    public DelegateRiaQuery(TContext context, Func<TContext, EntityQuery> createQueryDelegate)
        : base(context)
    {
        if (createQueryDelegate == null) throw new ArgumentException("createQueryDelegate");
        CreateQueryDelegate = createQueryDelegate;
    }

    protected override EntityQuery CreateQuery()
    {
        return CreateQueryDelegate(Context);
    }
}

public class DelegateRiaQuery<TContext, TEntity> : RiaQuery<TContext, TEntity> 
    where TContext : DomainContext 
    where TEntity : Entity
{
    protected Func<TContext, EntityQuery<TEntity>> CreateQueryDelegate;

    public DelegateRiaQuery(TContext context, Func<TContext, EntityQuery<TEntity>> createQueryDelegate) : base(context)
    {
        if (createQueryDelegate == null) throw new ArgumentException("createQueryDelegate");
        CreateQueryDelegate = createQueryDelegate;
    }

    protected override EntityQuery CreateQuery()
    {
        return CreateQueryDelegate(Context);
    }
}

用法如下:

public class MyModel : INotifyPropertyChanged
{
    ...

    public DelegateRiaQuery<MyContxt,MyEntity> MyModelOperation { get; private set; }

    public MyModel()
    {
        var context = new MyContext();
        MyModelOperation = new DelegateRiaQuery(context, c => c.GetMyModelEntitiesQuery(this.Property1));
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-24
    • 1970-01-01
    • 1970-01-01
    • 2018-06-21
    相关资源
    最近更新 更多