3

围绕这个领域肯定有很多问题,但在我的例子中我找不到任何帮助。

我遇到的问题是让我的 ViewModel,特别是 ViewModel 中的一个属性,更新到我的 View。下面是我的实现。我想我明白我要去哪里错了,但不知道如何解决它。

我有一个具有列表和编辑视图的模块。很简单地列出域对象,然后能够编辑域对象。

我的 xaml 将 DataContent 绑定到我的视图中的 ViewModel 属性。

然后我使用 INavigationAware.NavigateTo 方法导航到我的 ViewModel,这是我加载域对象的地方。

问题是显然这并没有反映到视图中。该视图已经有一个 ViewModel 的实例。当 ViewModel 使用 ObservableCollection 使用对象列表时,此方法运行良好。但是,这在使用简单对象甚至 ObservableObject 时不起作用。

有人可以帮助我理解或指出一些可以更好地实现我想要实现的目标的链接吗?

我的模块

public class MyModule : IModule
{
    private readonly IRegionManager _regionManager;

    public MyModule(IRegionManager regionManager)
    {
        _regionManager = regionManager;
    }

    public void Initialize()
    {
        _regionManager.RegisterViewWithRegion(Constants.MainRegionName, typeof(MyListView));
        _regionManager.RegisterViewWithRegion(Constants.MainRegionName, typeof(MyEditView));
    }
}

XAML

<UserControl
    DataContext="ViewModel">
    ...
    <TextBlock Text="{Binding Path=MyDomainObject.AProperty}" />
    ...

看法

public partial class MyEditView
{
    public readonly static string ViewName = "MyEditView";

    public MyEditView(MyEditViewModel viewModel)
    {
        InitializeComponent();
        ViewModel = viewModel;
    }

    public MyEditViewModel ViewModel
    {
        get { return DataContext as MyEditViewModel; }
        private set { DataContext = value; }
    }
}

视图模型

public class MyViewModel : INavigationAware
{
    private readonly IRegionManager _regionManager;

    public MyDomainObject MyDomainObject { get; set; }

    public void Load(ViewModelKey key)
    {
        // get domain object
        // this method worked when MyDomainObject was 
        // ObservableCollection<T> as just adding elements to list
        // where this is creating a new instance of MyDomainObject
        var id = parameter from navigationContext;
        MyDomainObejct = server.GetDomainObject(id);
    }

    public void OnNavigatedTo(NavigationContext navigationContext)
    {
        var key = key from navigationContext;
        Load(key);
    }
}

解决方案

public class MyEditViewModel : INavigationAware
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged([CallerMemberName]string propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    private MyDomainObject _myDomainObject;
    public MyDomainObject MyDomainObject
    {
        get
        {
            return _myDomainObject;
        }
        set
        {
            if (value != _myDomainObject)
            {
                _myDomainObject = value;
                NotifyPropertyChanged();
            }
        }
    }

看法

public partial class MyEditView
{
    public MyEditView(MyEditViewModel viewModel)
    {
        InitializeComponent();
        ViewModel = viewModel;

        ViewModel.PropertyChanged += ViewModel_PropertyChanged;
    }

    public MyEditViewModel ViewModel
    {
        get { return DataContext as MyEditViewModel; }
        private set { DataContext = value; }
    }

    private void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (!(sender is MyEditViewModel))
            return;

        ViewModel = (MyEditViewModel)sender;
    }
}
4

1 回答 1

3

要更新绑定,您需要在域对象的 set 访问器上实现INotifyPropertyChanged并引发 PropertyChanged 事件。

public event PropertyChangedEventHandler PropertyChanged = delegate {};


public MyDomainObject MyDomainObject
{
    get
    {
        return myDomainObject;
    }
    set
    {
        if(value != myDomainObject)
        {
            myDomainObject = value;
            RaisePropertyChanged("MyDomainObject");
        }
    }
}

private void RaisePropertyChanged(String p)
{
    PropertyChanged(this, new PropertyChangedEventArgs(p));
}

或者如在 Prism 书中,继承 NotificationObject 并调用 RaisePropertyChanged(()=> PropertyName) 这是重构安全的

于 2012-11-19T10:53:50.577 回答