C# NotifyPropertyChanged和ContentControl
我为我的问题挣扎了一个星期,我无法解决它。我正在编写一个MVVM WPF应用程序,它只有一个窗口(MainView)。在这个C# NotifyPropertyChanged和ContentControl,c#,wpf,C#,Wpf,我为我的问题挣扎了一个星期,我无法解决它。我正在编写一个MVVM WPF应用程序,它只有一个窗口(MainView)。在这个main视图中我想在需要时加载不同的UserControl。在应用程序启动中我正在加载MainViewModel。在MainViewModel的构造函数中,我正在加载第一个ViewModel(LoginViewModel)。我的MainView.xaml的原因是它显示了我想要的Login用户控件。所以直到现在一切都很好。在ActivePanel类中我正在保存CurrentV
main视图中
我想在需要时加载不同的UserControl
。在应用程序启动中
我正在加载MainViewModel
。在MainViewModel
的构造函数中,我正在加载第一个ViewModel
(LoginViewModel
)。我的MainView.xaml的原因是它显示了我想要的Login用户控件。所以直到现在一切都很好。在ActivePanel类中
我正在保存CurrentView
,因为在我的MainView.xaml中,我正在为ContentControl
绑定到我的CurrentView
。因此,除了视图的更改之外,一切都在工作,尽管CurrentView
的NotifyPropertyChanged
方法正在工作。我在想,我的错误在于xaml
(数据绑定)。希望你们能帮助我
这是我的MainView.xaml
,我想在其中加载不同的数据模板。就像我之前说过的:通过MainViewModel
的构造函数加载LoginViewModel
正在工作。更改为其他VieModels
也在起作用,但将数据绑定到ContentControl
是这里的大问题
<Window x:Class="App.View.MainView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:App.View"
mc:Ignorable="d"
xmlns:viewmodels="clr-namespace:App.ViewModels"
xmlns:views="clr-namespace:App.View"
xmlns:helper="clr-namespace:App.Helper"
Title="Betrooms" Height="500" Width="350">
<Window.Resources>
<DataTemplate x:Name="LoginUCTemplate" DataType="{x:Type viewmodels:LoginViewModel}">
<views:LoginUC DataContext="{Binding}"/>
</DataTemplate>
<DataTemplate x:Name="RegUCTemplate" DataType="{x:Type viewmodels:RegViewModel}">
<views:RegUC DataContext="{Binding}"/>
</DataTemplate>
<DataTemplate x:Name="HomeUCTemplate" DataType="{x:Type viewmodels:HomeViewModel}">
<views:HomeUC DataContext="{Binding}"/>
</DataTemplate>
</Window.Resources>
<Window.DataContext>
<viewmodels:ActivePanel/>
</Window.DataContext>
<Grid>
<ContentControl Content="{Binding CurrentView, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}"/>
</Grid>
</Window>
这是我的MainViewModel
:
namespace App.ViewModels
{
public class MainViewModel : ActivePanel
{
private LoginViewModel _loginViewModel;
public MainViewModel()
{
_loginViewModel = new LoginViewModel();
CurrentView = _loginViewModel;
}
}
}
这是我的LoginViewModel
,在这里我通过一个动作更改CurrentView
的值:
namespace App.ViewModels
{
public class LoginViewModel : ActivePanel
{
#region Member
private string _username;
private string _password;
bool login = false;
private HomeViewModel _homeViewModel;
private RegViewModel _regViewModel;
UserModel User = new UserModel();
#endregion
#region Properties
public ICommand RegActionCommand { get; set; }
public ICommand LogActionCommand { get; set; }
public string GetUsername
{
get { return _username; }
set
{
if (value != _username)
{
_username = value;
OnPropertyChanged("GetUsername");
}
}
}
public string GetPassword
{
get { return _password; }
set
{
if (value != _password)
{
_password = value;
OnPropertyChanged("GetPassword");
}
}
}
#endregion
#region Constructor
public LoginViewModel()
{
this.RegActionCommand = new RelayCommand(RegAction);
this.LogActionCommand = new RelayCommand(LogAction);
}
#endregion
#region Button-Action
private void LogAction(object obj)
{
_homeViewModel = new HomeViewModel();
CurrentView = _homeViewModel;
}
private void RegAction(object obj)
{
_regViewModel = new RegViewModel();
CurrentView = _regViewModel;
}
#endregion
}
}
我希望我的问题是可以理解的:ContentControl
绑定设置为CurrentView
,但是ContentControl
永远不会改变,尽管CurrentView
的属性在改变
谢谢大家。干杯,保罗。在命令处理程序中,您正在更改LoginViewModel
的CurrentView
属性。ContentControl
的DataContext
是MainViewModel
,因此它的内容绑定到MainViewModel
的CurrentView
属性
您需要在命令处理程序中设置MainViewModel
的属性。有不同的方法可以实现这一点,例如,您可以向LoginViewModel
添加构造函数参数,以传递对MainViewModel
的引用。您可以保存此引用,然后在命令处理程序中访问它
另一种可能是从LoginViewModel
中的命令引发事件或发送消息,并在MainViewModel
中处理它。这将减少ViewModels之间的耦合,但取决于您使用的机制和库,这可能会稍微复杂一些。您是否尝试过在ContentControl
下而不是在窗口资源下定义内容控制数据模板?我想我没有尝试过这样做。我对这种编码不是很熟悉。我尝试了很多在谷歌上找到的想法,但都不管用。您认为,您可以给出一个如何形成我的MainView.xaml的小例子吗?请注意,在单向绑定上设置UpdateSourceTrigger=PropertyChanged
,是毫无意义的。它只对双向或单向ToSource绑定有影响。设置Mode=OneWay
是多余的,因为这是默认设置。也就是说,您的代码应该如何工作?有一个ActivePanel
实例被设置为主窗口的DataContext,其中一个CurrentView
最初为空。该属性是如何变化的?感谢您提供有关{Mode=OneWay}的信息。我已经改变了。关于CurrentView的其他问题:正如我所理解的,我可以在运行时遵循CurrentView的值,是的,在程序开始时,该值为null,但构造函数会变成LoginVIewModel。当我点击die LoginView模型中的一个按钮时,CurrentView的值再次改变。因此,这一切都正常,但与CurrentView的绑定不起作用。我希望你能更详细地说明应该改变什么。干杯,保罗,谢谢你。我现在理解了我的代码中的错误。
namespace App.ViewModels
{
public class LoginViewModel : ActivePanel
{
#region Member
private string _username;
private string _password;
bool login = false;
private HomeViewModel _homeViewModel;
private RegViewModel _regViewModel;
UserModel User = new UserModel();
#endregion
#region Properties
public ICommand RegActionCommand { get; set; }
public ICommand LogActionCommand { get; set; }
public string GetUsername
{
get { return _username; }
set
{
if (value != _username)
{
_username = value;
OnPropertyChanged("GetUsername");
}
}
}
public string GetPassword
{
get { return _password; }
set
{
if (value != _password)
{
_password = value;
OnPropertyChanged("GetPassword");
}
}
}
#endregion
#region Constructor
public LoginViewModel()
{
this.RegActionCommand = new RelayCommand(RegAction);
this.LogActionCommand = new RelayCommand(LogAction);
}
#endregion
#region Button-Action
private void LogAction(object obj)
{
_homeViewModel = new HomeViewModel();
CurrentView = _homeViewModel;
}
private void RegAction(object obj)
{
_regViewModel = new RegViewModel();
CurrentView = _regViewModel;
}
#endregion
}
}