如何使用PRISM在WPF中导航并绑定DataContext

时间:2012-11-19 10:26:11

标签: c# wpf mvvm prism

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

我遇到的问题是将我的ViewModel,特别是ViewModel中的属性更新为我的View。以下是我的实施。我想我明白我哪里出错但不知道如何解决它。

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

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

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

问题是显然这不会反映回View。该视图已具有ViewModel的实例。当ViewModel使用ObservableCollection使用对象列表时,此方法工作正常。但是,当使用简单对象甚至是ObservableObject时,这不起作用。

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

MyModule的

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;
    }
}

1 个答案:

答案 0 :(得分:3)

要使绑定更新,您需要实现INotifyPropertyChanged并在域对象的set访问器上引发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(()=&gt; PropertyName),这是重构安全的