首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用MVVM-Light和WCF RIA服务创建可混合项目

如何使用MVVM-Light和WCF RIA服务创建可混合项目
EN

Stack Overflow用户
提问于 2010-07-13 18:09:08
回答 2查看 1.2K关注 0票数 2

我想使用MVVM模式构建我的业务应用程序。我选择MVVM-Light是因为它适合我的需求。在我见过的所有关于MVVM-Light的例子中,都没有人使用WCF RIA。经典的MIX10示例使用同一项目中的服务,而WCF在Web项目中创建服务。问题是:构建WCF Ria创建的整个DomainContex的接口看起来非常困难(对我来说肯定很难!)但是如果没有接口,我怎么能构建一个假的DomainContex来在Blend和测试中使用呢?我是不是遗漏了什么?谢谢。

EN

回答 2

Stack Overflow用户

发布于 2010-07-21 02:24:58

实际上,我使用的解决方案是可混合的,并且使混合过程更加简单。

下面是我如何使用这个框架来实现这一点的示例:

代码语言:javascript
复制
 public class FolderViewModel : VMBase
{
    private string _subject = string.Empty;
    private string _folderName = string.Empty;
    private string _service = string.Empty;
    private string _dept = string.Empty;
    private string _efolderid = string.Empty;
    private string _timingName = string.Empty;
    private WorkplanBase _planBase = null;
    private IEnumerable<PSCustomList> _timingOptions = null;
    private decimal _totalvalue = 0;


    public FolderViewModel()
    {
        registerForMessages();

        if (IsInDesignMode)
        {
            // Code runs in Blend --> create design time data.
            EFOLDERID = "0123456790123456790123456791";
            Subject = "9999-00 - This is a test nVision Subject";
            Service = "AUDCOMP";
            Department = "AUDIT";
            FolderName = "NVSN003000";


            List<PSCustomList> listItems = new List<PSCustomList>();
            listItems.Add(new PSCustomList()
            {
                ID = "1234",
                ParameterValue = "Busy Season"
            });
            listItems.Add(new PSCustomList()
            {
                ID = "1134",
                ParameterValue = "Another Season"
            });

            _timingOptions = listItems.ToArray();
            _totalvalue = 12000;

            PlanBase = new WorkplanBase()
            {
                ClientFee = 15000,
                Timing = "1234"
            };
        }
    }
}

然后,在绑定在ViewModelLocator类中的Acutal View模型的构造器中定义所有样本数据。当您在blend中时,VMBase负责不尝试实例化DataContext。

票数 2
EN

Stack Overflow用户

发布于 2010-07-20 06:23:02

我发现对我来说效果很好的是以下内容(我从MVVM light和RIA业务模板中提取了部分内容)。

我构建了一个新的ViewModelBase类,继承自MVVM Light的ViewModelBase类,在这个类中我实现了一个DomainContext、可能挂起的操作列表、当前操作、IsBusy属性、一个SaveCommand和一个protected方法来记录由ViewModels创建的、从这个类继承的任何操作。

下面是一个示例:

代码语言:javascript
复制
public class VMBase : ViewModelBase
{
    protected DomainContext _context;
    protected IList<OperationBase> operations = new List<OperationBase>();
    protected OperationBase currentOperation;

    public VMBase()
    {
        if (IsInDesignMode == false)
        {
            _context = new BudgetContext();
            _context.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(_context_PropertyChanged);
        }
        SaveChangesCommand = new RelayCommand(
                () =>
                {
                    currentOperation = _context.SubmitChanges((so) =>
                    {
                        DispatcherHelper.CheckBeginInvokeOnUI(() =>
                        {
                            OnSaveComplete();
                            SaveChangesCommand.RaiseCanExecuteChanged();
                            CancelChangesCommand.RaiseCanExecuteChanged();
                        });
                    },
                        null);
                    logCurrentOperation();
                },
                () =>
                {
                    return _context != null && _context.HasChanges;
                });
        CancelChangesCommand = new RelayCommand(
                () =>
                {
                    _context.RejectChanges();
                    SaveChangesCommand.RaiseCanExecuteChanged();
                    CancelChangesCommand.RaiseCanExecuteChanged();
                },
                () =>
                {
                    return _context != null && _context.HasChanges;
                });
    }

    /// <summary>
    /// This is called after Save is Completed
    /// </summary>
    protected virtual void OnSaveComplete() { }

    void _context_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "HasChanges")
        {
            DispatcherHelper.CheckBeginInvokeOnUI(() =>
            {
                SaveChangesCommand.RaiseCanExecuteChanged();
                CancelChangesCommand.RaiseCanExecuteChanged();
            });
        }
    }

    /// <summary>
    /// Bind to Busy Indicator to show when async server
    /// call is being made to submit or load data via the
    /// DomainContext/
    /// </summary>
    public bool IsWorking
    {
        get
        {
            if (currentOperation != null)
                return !currentOperation.IsComplete;
            else
            {
                return operations.Any(o => o.IsComplete == false);
            }
        }
    }

    /// <summary>
    /// Call this command to save all changes
    /// </summary>
    public RelayCommand SaveChangesCommand { get; private set; }
    /// <summary>
    /// Revert all changes not submitted
    /// </summary>
    public RelayCommand CancelChangesCommand { get; private set; }

    /// <summary>
    /// Occurs after each operation is completed, which was registered with logCurrentOperation()
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void currentOperation_Completed(object sender, EventArgs e)
    {
        currentOperation = null;
        operations.Remove((OperationBase)sender);
        DispatcherHelper.CheckBeginInvokeOnUI(() =>
        {
            RaisePropertyChanged("IsWorking");
        });
    }

    /// <summary>
    /// Logs and notifies IsBusy of the Current Operation
    /// </summary>
    protected void logCurrentOperation()
    {
        currentOperation.Completed += new EventHandler(currentOperation_Completed);
        operations.Add(currentOperation);
        RaisePropertyChanged("IsWorking");
    }

    /// <summary>
    /// Just make sure any async calls are done
    /// </summary>
    public override void Cleanup()
    {
        // Clean own resources if needed
        foreach (OperationBase op in operations)
        {
            if (op.IsComplete == false)
            {
                if (op.CanCancel)
                    op.Cancel();
            }
        }

        base.Cleanup();
    }
}

然后,在实际的视图模型中,您可以专注于视图模型的属性和命令-所有的域上下文都已经为您连接好了。只需使用_context属性-例如:

代码语言:javascript
复制
void loadFolderInfo()
    {
        if (_context != null)
        {
            EntityQuery<eFolder> query = _context.GetEFoldersByFolderQuery(_efolderid);
            currentOperation =
                _context.Load<eFolder>(query,
                new Action<LoadOperation<eFolder>>((lo) =>
                    {
                        if (lo.HasError)
                        {
                            Messenger.Default.Send<DialogMessage>(
                                new DialogMessage(lo.Error.Message, (mbr) =>
                                    {}));
                        }
                        DispatcherHelper.CheckBeginInvokeOnUI(
                            () =>
                            {
                                eFolder myFolder = lo.Entities.First();
                                Subject = myFolder.eSubject;
                                FolderName = myFolder.eFolderName;


                            });

                    }), null);
            logCurrentOperation();
        }
    }

属性可能如下所示:

代码语言:javascript
复制
public string EFOLDERID
    {
        get
        {
            return _efolderid;
        }

        set
        {
            if (_efolderid == value)
            {
                return;
            }

            var oldValue = _efolderid;
            _efolderid = value;

            // Update bindings and broadcast change using GalaSoft.MvvmLight.Messenging
            RaisePropertyChanged("EFOLDERID", oldValue, value, true);
            loadFolderInfo();
        }
    }

关键部分是VMBase类处理DomainContext的所有连接和管理。要做到这一点,在你的ViewModel实现中,确保将任何_context.BaseOperationCall(..)的返回值赋给currrentOperation,然后立即调用logCurrentOperation。之后,它就不用插手了。然后,你可以将BusyIndicator绑定到你的IsWorking属性上,这样你就有了一个简化的RIA实现。

希望这篇文章能帮助你入门。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3236095

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档