C# WPF mvvm轻型使用具有双向绑定的数据服务

C# WPF mvvm轻型使用具有双向绑定的数据服务,c#,wpf,mvvm,mvvm-light,C#,Wpf,Mvvm,Mvvm Light,我通过构建一个解决我在工作中遇到的一个简单问题的示例来自学MVVM light。我们有两个ID记录,一个存储为long,一个存储为int。对于大ID,int字段环绕。此程序显示给定int的可能longID 我正在尝试使用SimpleIocDataServices解决这个问题,因此这个例子比它需要的复杂得多 数据服务是一个简单的类(CallIDConverter),它保存ID并计算其他值,如果给定int,则计算其他可能的long值 当用户键入新值时,将更新类,因此将调用RaisePropertyC

我通过构建一个解决我在工作中遇到的一个简单问题的示例来自学MVVM light。我们有两个ID记录,一个存储为
long
,一个存储为
int
。对于大ID,
int
字段环绕。此程序显示给定
int
的可能
long
ID

我正在尝试使用
SimpleIoc
DataServices解决这个问题,因此这个例子比它需要的复杂得多

数据服务是一个简单的类(
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>(); } 
    }
}


这意味着
calledconverter
不需要从
observateObject
继承。问题是ViewModel需要知道在对模型类调用方法时受到影响的所有内容。在我看来,这似乎不是一个好主意。

没有任何东西监视
数据
,因此,提出它已发生变化根本没有任何作用。即使我正在监视
数据.CCIRPrimaryID
?如果
数据
发生更改,它当然应该检查
数据
的属性是否发生了正确的更改,因为绑定(未发布)很可能是
{binding CCIRPrimaryID}
,它不知道
数据
(私有属性)。属性更改通知完全基于字符串,XAML绑定从其路径中的更改通知中查找属性名称。由于
数据
没有显示为
CCIRPrimaryID
的路径组件,因此不会发生任何事情。没有任何东西会监视
数据
,因此,提出它已更改的信息根本不会起任何作用。即使我正在监视
数据.CCIRPrimaryID
?如果
数据
发生更改,它当然应该检查
数据
的属性是否发生了正确的更改,因为绑定(未发布)很可能是
{binding CCIRPrimaryID}
,它不知道
数据
(私有属性)。属性更改通知完全基于字符串,XAML绑定从其路径中的更改通知中查找属性名称。由于
数据
不会显示为
CCIRPrimaryID
的路径组件,因此不会发生任何事情。
public class CallIdDataService : IDataService
{
    public void GetData(Action<CallIdConverter, Exception> callback)
    {
        var item = new CallIdConverter();
        callback(item, null);
    }
}
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);
    }
}
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);