我在更新我正在处理的Windows Phone 7应用程序界面时出现问题。
我有MainPage.xaml
及其MainViewModel.cs
,用于处理子视图usercontrol ChildView1.xaml
在主页中的显示方式。 ChildView1的ViewModel也是Child1ViewModel.cs
。基本上,从MainPage触发myToggleButton
会触发DataStateBehavior
进入显示或隐藏状态以分别显示或隐藏ChildView1.xaml
。 DataStateBehavior绑定到布尔值CanShowView
,而myToggleButton
绑定到Icommand
名为ButtonChecked
的{{1}},其中继函数SwitchVisibility
将反转CanShowView
1}}布尔值来显示或隐藏视图。由于我使用的MVVM灯的RaisePropertyChanged
,一切正常。
但是,ChildView1.xaml
有一个myCloseButton
,它应该从MainViewModel调用SwitchVisibility
函数,后者又会还原CanShowView
和RaisePropertyChanged
在CanShowView
中应该触发ChildView1
关闭,但问题是视图保持可见并且由于某种原因永远不会关闭!我通过调试器注意到RaisePropertyChanged
中的CanShowView
似乎没有触发。我想这就是问题所在。我做错了什么?我该怎么强迫它开火呢?我使用了多个RaisePropertyChanged
但是似乎没有人发射,即使degugger显示我的函数中的值确实发生了变化。
这是我的代码。 MainPage.xaml中:
<phone:PhoneApplicationPage
...
>
<phone:PhoneApplicationPage.DataContext>
<Binding Path="Main" Source="{StaticResource Locator}"/>
</phone:PhoneApplicationPage.DataContext>
...
<Grid x:Name="LayoutRoot">
...
<ToggleButton x:Name="myToggleButton" Command="{Binding Main.ButtonChecked, Source={StaticResource Locator}}" >
<local:ChildView1 x:Name="myChildView1" Grid.Row="0" RenderTransformOrigin="0.5,0.5">
<i:Interaction.Behaviors>
<ec:DataStateBehavior Binding="{Binding Main.CanShowView, Source={StaticResource Locator}}" Value="True" TrueState="showChildView1" FalseState="hideChildView1"/>
</i:Interaction.Behaviors>
<local:ChildView1.RenderTransform>
<CompositeTransform/>
</local:ChildView1.RenderTransform>
</local:ChildView1>
</Grid>
</phone:PhoneApplicationPage>
MainViewModel.cs:
public class MainViewModel : ViewModelBase
{
public ICommand ButtonChecked { get; private set; }
public MainViewModel()
{
ButtonChecked = new RelayCommand(() => SwitchVisibility());
}
public void SwitchVisibility()
{
CanShowView = !CanShowView;
RaisePropertyChanged("CanShowView");
}
bool _canShowView = true;
public bool CanShowView
{
get { return _canShowView; }
set
{
if (value != _canShowView)
{
_canShowView = value;
RaisePropertyChanged("CanShowView");
}
}
}
}
ChildView1.xaml:
<UserControl x:Class="myApp.Views.ChildView1"
....
DataContext="{Binding Child1VM, Source={StaticResource Locator}}"
>
<Grid x:Name="HomeGrid">
<Button x:Name=myCloseButton Command="{Binding Child1VM.CloseChildViewCmd, Source={StaticResource Locator}}"/>
...
</Grid>
</UserControl>
Child1ViewModel.cs:
namespace myApp
{
public class Child1ViewModel : ViewModelBase
{
public ICommand CloseChildViewCmd { get; private set; }
public Child1ViewModel()
{
CloseChildViewCmd = new RelayCommand(() => ExecuteCloseChildViewCmd());
}
public void ExecuteCloseChildViewCmd()
{
MainPage mainPage = new MainPage();
MainViewModel mainVM = new MainViewModel();
mainPage.DataContext = mainVM;
mainVM.SwitchVisibility();
}
}
}
注意:我只是一个初学程序员,所以我处理问题或程序本身的方式可能有问题,因此我对任何建议持开放态度,并且非常欢迎代码示例。在经过大量研究和试验许多似乎无法发挥作用的事情之后,我已经坚持了很多天这个问题。我花时间详细地写了这个问题,我真的希望能在这里找到解决方案。如果您需要了解更多细节,请与我们联系。 提前谢谢。
编辑:我读过创建视图的新实例不是解决方案。我怎样才能获取MainView
的函数并获取属性?
编辑:正如OmegaMan所建议的,我使用静态定义来调用我的函数。
所以更新了MainViewModel.cs
:
公共类MainViewModel:ViewModelBase
{
public ICommand ButtonChecked {get;私人集; }
private static MainViewModel Primary {get;组; }
public MainViewModel()
{
ButtonChecked = new RelayCommand(() => SwitchVisibility());
Primary = this;
}
public void SwitchVisibility()
{
CanShowView = !CanShowView;
RaisePropertyChanged("CanShowView");
}
public static void SwitchViewStatic()
{
Primary.SwitchVisibility();
}
bool _canShowView = true;
public bool CanShowView
{
get { return _canShowView; }
set
{
if (value != _canShowView)
{
_canShowView = value;
RaisePropertyChanged("CanShowView");
}
}
}
}
更新后的Child1ViewModel.cs
:
命名空间myApp
{
公共类Child1ViewModel:ViewModelBase
{
public ICommand CloseChildViewCmd {get;私人集; }
public Child1ViewModel()
{
CloseChildViewCmd = new RelayCommand(()=&gt; ExecuteCloseChildViewCmd());
}
public void ExecuteCloseChildViewCmd()
{
MainViewModel.SwitchViewStatic();
}
}
}
MainViewModel中的所需函数由myCloseButton从子视图调用,但CanShowView
仍然不会被引发以允许DataStateBehavior收听它,更新UI ...所以我仍然在impass。
答案 0 :(得分:1)
问题是您正在向新的MainPage对象发送消息并查看模型,而不是现有的。
您需要的是代表或活动。诀窍是将主页面连接到子页面。
如果您需要将它们分开,则需要一个对象来发送事件。这称为事件聚合器或信使。您的主视图模型需要订阅子视图模型在执行命令时将发送的CloseChild事件。事件聚合器传输消息。
注意:大多数MVVM框架实现了视图模型可用于发送和接收消息/事件的某种信使。
如果您想自己实现一个,请查看here以创建一个。
答案 1 :(得分:1)
让孩子们持有对主视图模型的引用没有错,但为什么控件会创建一个新的MainViewModel?传入MainViewModel并从中调用SwitchVisibility ...或在MainVM上创建一个静态方法,该方法将访问实际VM并调用实例SwitchVisiblity。
---更新以显示来自MainVM的静态方法访问
public class MainViewModel : ViewModelBase
{
private static MainViewModel Primary { get; set; }
public MainViewModel()
{
Primary = this;
}
public static void SwitchViewStatic()
{
Primary.SwitchVisibility();
}
public void SwitchVisibility()
{
...
}
}