WPF mvvm Light使用具有双向绑定的dataservice

时间:2016-01-04 16:17:10

标签: c# wpf mvvm mvvm-light

我通过构建一个解决我工作中遇到的简单问题的例子来教自己MVVM光。我们有两个ID记录,一个记录为long,一个记录为int。对于大型ID,int字段包含在内。此计划会显示给定long的可能int个ID。

我正在尝试使用SimpleIoc DataServices,所以这个例子比它需要的要复杂得多。

DataService是一个简单的类(CallIDConverter),它保存ID并计算其他值,如果给出int,则计算其他可能的long值。

当用户键入新值时,正在更新类,因此正在调用RaisePropertyChanged(),但视图未更新。这是由于我使用DataService的方式吗?或者我只是在某个地方错过了RaisePropertyChanged()

ViewModelLocator.cs:

public class ViewModelLocator
{
    static ViewModelLocator()
    {
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

        if (ViewModelBase.IsInDesignModeStatic)
        {
            SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
        }
        else
        {
            SimpleIoc.Default.Register<IDataService, CallIdDataService>();
        }
        SimpleIoc.Default.Register<MainViewModel>();
    }
    public MainViewModel Main
    {
        get { ServiceLocator.Current.GetInstance<MainViewModel>(); } 
    }
}

CallIdDataService.cs:

public class CallIdDataService : IDataService
{
    public void GetData(Action<CallIdConverter, Exception> callback)
    {
        var item = new CallIdConverter();
        callback(item, null);
    }
}

CallIDConverter.cs

public class CallIdConverter : ObservableObject
{
    private static long _totalNumberOfInts = Convert.ToInt64(Int32.MaxValue) - Convert.ToInt64(Int32.MinValue) + 1;

    private int _shorewareCallID;
    private long _ccirPrimaryID;
    private List<long> _ccirPossiblePrimaryIDs;

    public int ShorewareCallID { get { return _shorewareCallID; } }
    public long CCIRPrimaryID { get { return _ccirPrimaryID; } }
    public ReadOnlyCollection<long> CCIRPossiblePrimaryIDs { get { return _ccirPossiblePrimaryIDs.AsReadOnly(); } }

    public CallIdConverter()
    {
        this._shorewareCallID = 0;
        this._ccirPrimaryID = 0L;
        this._ccirPossiblePrimaryIDs = new List<long>();
    }

    public void SetShorewareCallID(int callID)
    {
        this._shorewareCallID = callID;
        this._ccirPrimaryID = callID > 0L ? (long)callID : (long)callID + _totalNumberOfInts;
        this._ccirPossiblePrimaryIDs.Clear();

        for (int i = 0; i < 5; i++)
        {
            _ccirPossiblePrimaryIDs.Add((long)callID + (i * _totalNumberOfInts));
        }
        RaisePropertyChanged(() => ShorewareCallID);
        RaisePropertyChanged(() => CCIRPrimaryID);
        RaisePropertyChanged(() => CCIRPossiblePrimaryIDs);
    }

    public void SetCCIRPrimaryID(long primaryID)
    {
        this._shorewareCallID = (int)primaryID;
        this._ccirPrimaryID = primaryID;
        this._ccirPossiblePrimaryIDs.Clear();
        RaisePropertyChanged(() => ShorewareCallID);
        RaisePropertyChanged(() => CCIRPrimaryID);
        RaisePropertyChanged(() => CCIRPossiblePrimaryIDs);
    }
}

MainViewModel.cs:

public class MainViewModel : ViewModelBase
{
    private readonly IDataService _dataService;
    private CallIdConverter Data { get; set; }

    public MainViewModel(IDataService dataService)
    {
        _dataService = dataService;
        _dataService.GetData(
            (item, error) =>
            {
                if (error != null)
                {
                    // Report error here
                    return;
                }
                this.Data = item;
            });
    }
    public int ShorewareCallID
    {
        get { return Data.ShorewareCallID; }
        set
        {
            if (Data.ShorewareCallID == value) { return; }
            Data.SetShorewareCallID(value);
            RaisePropertyChanged(() => Data);
        }
    }
    public long CCIRPrimaryID
    {
        get { return Data.CCIRPrimaryID; }
        set
        {
            if (Data.CCIRPrimaryID == value) { return; }
            Data.SetCCIRPrimaryID(value);
            RaisePropertyChanged(() => Data);
        }
    }
    public ObservableCollection<long> CCIRPossiblePrimaryIDs
    {
        get { return new ObservableCollection<long>(Data.CCIRPossiblePrimaryIDs); }
    }
}

在摆弄之后,我发现如果我替换

它会起作用
RaisePropertyChanged(() => Data);

RaisePropertyChanged(() => ShorewareCallID);
RaisePropertyChanged(() => CCIRPrimaryID);
RaisePropertyChanged(() => CCIRPossiblePrimaryIDs);

这意味着CallIDConverter不需要继承ObservableObject。这个问题是ViewModel需要知道在模型类上调用方法时受影响的所有内容。在我看来这不是一个好主意。

0 个答案:

没有答案