我还在学习棱镜,我想了解导航。阅读了手册并关注@brianlagunas MVVM在网上制作了简单的网络研讨会,我决定尝试一个小项目并看看。当我尝试导航到一个视图时,我得到一个stackoverflow异常,该视图的视图模型数据绑定到我的视图上的某些控件。以下是代码:
带有空viewmodel的配置文件视图:
<UserControl x:Class="SampleLogin.Views.Profile"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
xmlns:local="clr-namespace:SampleLogin.Views"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<TextBlock x:Name="ProfileTextBlock" HorizontalAlignment="Center" Margin="74,29,78,0" TextWrapping="Wrap" Text="PROFILE PAGE" VerticalAlignment="Top" Height="45" Width="148" FontSize="21.333" FontWeight="Bold"/>
<TextBlock x:Name="Username" HorizontalAlignment="Left" Height="26" Margin="103,96,0,0" TextWrapping="Wrap" Text="{Binding username}" VerticalAlignment="Top" Width="130"/>
<TextBlock x:Name="LoginTime" HorizontalAlignment="Left" Margin="109,152,0,0" TextWrapping="Wrap" Text="{Binding LoginTime}" VerticalAlignment="Top" Width="124" Height="33"/>
<Label x:Name="label" Content="Username :" HorizontalAlignment="Left" Margin="10,96,0,0" VerticalAlignment="Top" Width="71" FontWeight="Bold"/>
<Label x:Name="label1" Content="Login-Time:" HorizontalAlignment="Left" Height="26" Margin="12,159,0,0" VerticalAlignment="Top" Width="86" FontWeight="Bold"/>
</Grid>
但它有一个空的viewmodel并且加载正常。
这是另一个视图,其中包含一个与其viewmodel
数据绑定的简单形式<UserControl x:Class="SampleLogin.Views.LoginUser"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
xmlns:local="clr-namespace:SampleLogin.Views"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="325">
<Grid>
<Label x:Name="usernameLabel" Content="Username :" HorizontalAlignment="Left" Margin="10,93,0,0" VerticalAlignment="Top" Width="113" Height="35" FontSize="18.667" FontWeight="Bold"/>
<Label x:Name="label" Content="Password :
" HorizontalAlignment="Left" Margin="10,146,0,0" VerticalAlignment="Top" Width="100" Height="38" FontSize="18.667" FontWeight="Bold"/>
<TextBox x:Name="Username" HorizontalAlignment="Left" Height="35" Margin="132,93,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="178" Text="{Binding Username, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<PasswordBox x:Name="passwordBox" HorizontalAlignment="Left" Margin="132,146,0,0" VerticalAlignment="Top" Width="178" Height="35"/>
<Button x:Name="Loginbtn" Content="Login" HorizontalAlignment="Left" Margin="85,208,0,0" VerticalAlignment="Top" Width="89" Height="42" FontSize="18.667" FontWeight="Bold"
Command="{Binding LoginCommand}" CommandParameter="{Binding ElementName=passwordBox}" />
<Button x:Name="Logoutbtn" Content="Logout" HorizontalAlignment="Left" Margin="230,208,0,0" VerticalAlignment="Top" Width="80" Height="42" FontWeight="Bold" FontSize="18.667"/>
</Grid>
这是它所绑定的viewmodel:只是为了理解这个概念,它非常简单:
public class LoginUserViewModel : BindableBase
{
private AuthenticationService _auth;
public DelegateCommand<object> LoginCommand { get; set; }
public LoginUserViewModel(AuthenticationService auth)
{
_auth = auth;
LoginCommand = new DelegateCommand<object>(LoginUser, CanLoginUser);
}
private void LoginUser(object obj)
{
var passwdbox = obj as PasswordBox;
_auth.LoginUser(Username, passwdbox.SecurePassword);
}
private bool CanLoginUser(object obj)
{
var password = obj as PasswordBox;
return string.IsNullOrWhiteSpace(Username);
}
private string _username = "Enter Username here";
public string Username
{
get { return _username; }
set { SetProperty(ref _username, value); }
}
}
这是MainWindowViewmodel,它使用主窗口视图顶部的按钮处理导航。
public class MainWindowViewModel : BindableBase
{
IRegionManager _regions;
public DelegateCommand<string> NavigationCommand { get; set; }
public MainWindowViewModel(IRegionManager regions)
{
_regions = regions;
NavigationCommand = new DelegateCommand<string>(Navigate);
}
private void Navigate(string uri)
{
_regions.RequestNavigate("ContentRegion", uri);
}
}
最后,这是绑定到viewmodel的MainWindowViewModel:
<Window x:Class="SampleLogin.Views.MainWindow"
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:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
xmlns:local="clr-namespace:SampleLogin.Views"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<Button Content="Login" Margin="5" Command="{Binding NavigationCommand, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" CommandParameter="LoginUser" />
<Button Content="Home" Margin="5" Command="{Binding NavigationCommand, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" CommandParameter="Home"/>
<Button Content="Profile" Margin="5" Command="{Binding NavigationCommand}" CommandParameter="Profile"/>
</StackPanel>
<ContentControl Grid.Row="1" prism:RegionManager.RegionName="ContentRegion" />
</Grid>
我发现这很奇怪。只要我将ViewModel留空,当我单击屏幕顶部的按钮进行导航时,第一个视图就会起作用。与具有该表单的视图相同,如果我注释掉ViewModel,它会毫无问题地导航,显示表单和所有内容。但是如果在viewmodel中有数据绑定,我会得到异常。有任何想法吗?!我被踩了,不知道我的错误在哪里。
编辑:
考虑到这个问题并尝试将其向前移动,我发现错误来自于我的LoginUserViewModel具有构造函数参数是我遇到错误的原因,尝试在引导程序寄存器LoginUserViewmodel&#39;中使用unity容器。 s依赖,但我仍然得到错误,任何人的想法?
答案 0 :(得分:0)
在做了一些搜索和问题询问之后,我得到了这个问题的答案。我和很棒的@brianLagunas交谈,并与他分享了我的代码,他了解了我遇到的问题。它在一个域模型中,我没有包含在我的帖子中。
public class User : IUser
{
public User()
{
}
public User(User user){} //this is the problem line
[Required]
[Key]
public int UserId { get; set; }
[Required(ErrorMessage ="You must supply a Username")]
[DataType(DataType.Text)]
public string Username { get; private set; }
[Required(ErrorMessage = "You must enter a valid password to Login!")]
public SecureString Password { get; private set; }
[DataType(DataType.Time)]
[Required]
public TimeSpan TimeLoggedIn { get; private set; }
[DataType(DataType.Date)]
public DateTime LoginHistory { get; private set; }
public void SetUserDetails(string username, TimeSpan date, DateTime History)
{
if(string.IsNullOrWhiteSpace(username))
{
throw new ArgumentNullException("You cannot have any of the Login Fields empty..!");
}
Username = username;
TimeLoggedIn = date;
LoginHistory = History;
}
}
第二个构造函数包含一个无限循环,这是我得到的堆栈溢出错误。删除该构造函数修复了问题,一切都很顺利。