我正在构建一个WPF MVVM应用程序但是我在从子视图模型更新父视图时遇到了问题。
我在父视图模型上调用doAction()方法,该方法更新属性并引发PropertyChangeEvent。当从MainViewModel调用此方法时,一切都很好,但是当我从子视图模型调用相同的方法时,会引发PropertyChangedEvent get,但视图不会更新。
示例:
ChildViewModel()
{
private ParentViewModel parent;
parent.doAction(); // Raised event but MainView doesn't update
}
ParentViewModel()
{
public void doAction()
{
this.Property = true;
OnPropertyChange("Property");
}
}
我的视图是使用XAML创建的:
<MainView>
<TabItem>
<view:ChildView/>
</TabItem>
</MainView>
Propery Change事件如此提出:
protected void OnPropertyChanged(string name)
{
LOGGER.Info("Property Changed: " + name);
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
我的问题是如何让父视图监听并更新由子视图引发的属性更改事件。
编辑:
基类:
public abstract class AbstractBaseViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public ICommand CloseCommand { get; set; }
public AbstractBaseViewModel()
{
this.CloseCommand = new CloseCommand(this);
}
public void CloseWindow()
{
Application.Current.MainWindow.Close();
}
protected void OnPropertyChanged(string name)
{
LOGGER.Info("Property Changed: " + name);
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
父ViewModel:
public class ParentViewModel : AbstractBaseViewModel
{
private Dispatcher dispatcher;
private bool visible;
public bool Visible
{
get { return visible; }
set { visible= value; OnPropertyChanged("Visible"); }
}
public MainWindowViewModel()
{
this.dispatcher = Dispatcher.CurrentDispatcher;
this.manager = manager;
}
public void ShowTab(){
this.Visible = true;
}
}
儿童视图模型:
public class ChildViewModel : AbstractBaseViewModel
{
private ParentViewModel parentVm;
public GeneralViewModel(ParentViewModel vm)
{
this.parentVm= vm;
}
public void Command(){
vm.ShowTab();
}
}
ParentView Xaml:
<TabItem Header="ViewWeWantToHide/Show"
Visibility="{Binding Visible,Converter={converter:BooleanToVisibilityConverter}}">
<views:SomeOtherView/>
</TabItem>
<TabItem Header="ChildView Tab">
<views:ChildView/>
</TabItem>
答案 0 :(得分:1)
如果没有看到所有代码,很难猜出导致问题的原因。但是,我不得不说在WPF中更常见的是在UI中显示视图模型实例并让WPF自动显示相关视图,而不是直接显示视图。如果您使用视图模型而不是视图,那么您将可以从父视图模型访问子视图模型。
如果您这样做,或者确实可以从父视图模型访问子视图模型,那么我建议您使用简单的delegate
将子视图模型中的“消息”传递给父视图而不是模型。您甚至可以定义无参数delegate
并使用它来发送信号,而不是任何属性值。
您可以声明delegate
,向您的孩子UserControl
添加该类型的属性,并在主视图模型中附加处理程序。然后,您可以从您的孩子delegate
调用UserControl
,并在父视图模型的处理程序中调用您的方法。有关此技术的更多信息,请参阅我对Passing parameters between viewmodels问题的回答(它回答了类似但不完全相同的问题)。
答案 1 :(得分:0)
感谢大家的帮助。
我发现这个问题与WPF无关,实际上是我在子视图上设置datacontext的一个产物。在我的父窗口中,我使用Unity容器创建并注册了ParentViewModel的单例实例。然后将此实例注入到所有子视图中,问题是在创建父视图模型并使用unity容器注册之前调用了InitializeComponent方法,这意味着所有子视图都接收完全不同的实例。
不工作:
public MainWindow()
{
InitializeComponent();
if (DesignerProperties.GetIsInDesignMode(this))
{
this.DataContext = new ParentViewModel();
}
else
{
IUnityContainer container = UnityFactory.Retrieve();
ParentViewModel parentVM = container.Resolve<ParentViewModel>();
container.RegisterInstance<ParentViewModel>(parentVM);
this.DataContext = parentVM;
}
}
工作:
public MainWindow()
{
if (DesignerProperties.GetIsInDesignMode(this))
{
this.DataContext = new ParentViewModel();
}
else
{
IUnityContainer container = UnityFactory.Retrieve();
ParentViewModel parentVM = container.Resolve<ParentViewModel>();
container.RegisterInstance<ParentViewModel>(parentVM );
this.DataContext = parentVM;
}
/**
* Initialize after registering parent VM and setting the datacontext
*/
InitializeComponent();
}