我的目标是为用户创建一个登录屏幕,以便在进入应用程序之前登录。 我开始使用PRISM来控制我的模块,视图,视图模型等......
现在我的问题是,我有一个类似于下面的人类:
public class Person : DeletableSupport, IObserver, IDataErrorInfo, IActivatable
{
public class Properties
{
public const string Name = "Person_Name";
public const string SurName = "Person_SurName";
public const string Alias = "Person_Alias";
public const string Password = "Person_Password";
}
//TODO Add Rights bitarray type of thing
//TODO add IObserver stuff
private string _Name;
private string _SurName;
private string _Alias;
private string _Password;
private NotificationList _nList;
private ReminderList _rList;
private ProjectList _pList;
private DayPoolList _dpList;
private EventList _eList;
private ActivityList _aList;
[Transient]
private IActivator _activator;
#region Get/Set
public string Name
{
get
{
Activate(ActivationPurpose.Read);
return this._Name;
}
set
{
if (this._Name != value)
{
Activate(ActivationPurpose.Write);
this._Name = value;
}
}
}
public string Password
{
get
{
Activate(ActivationPurpose.Read);
return this._Password;
}
set
{
if (this._Password != value)
{
Activate(ActivationPurpose.Write);
this._Password = value;
RaisePropertyChanged(Person.Properties.Password);
}
}
}
public string SurName
{
get
{
Activate(ActivationPurpose.Read);
return this._SurName;
}
set
{
if (this._SurName != value)
{
Activate(ActivationPurpose.Write);
this._SurName = value;
}
}
}
public string Alias
{
get
{
Activate(ActivationPurpose.Read);
return this._Alias;
}
set
{
if (this._Alias != value)
{
Activate(ActivationPurpose.Write);
this._Alias = value;
RaisePropertyChanged(Person.Properties.Alias);
}
}
}
#endregion
public Person()
{
this._aList = new ActivityList();
this._dpList = new DayPoolList();
this._eList = new EventList();
this._nList = new NotificationList();
this._pList = new ProjectList();
this._rList = new ReminderList();
}
#region ListObjects
public ActivityList getActivityList()
{
Activate(ActivationPurpose.Read);
return this._aList;
}
public DayPoolList getDayPoolList()
{
Activate(ActivationPurpose.Read);
return this._dpList;
}
public EventList getEventList()
{
Activate(ActivationPurpose.Read);
return this._eList;
}
public NotificationList getNotificationList()
{
Activate(ActivationPurpose.Read);
return this._nList;
}
public ProjectList getProjectList()
{
Activate(ActivationPurpose.Read);
return this._pList;
}
public ReminderList getReminderList()
{
Activate(ActivationPurpose.Read);
return this._rList;
}
public ObservableCollectionEx<Activity> ActivityList
{
get
{
Activate(ActivationPurpose.Read);
return this._aList.getObsCollection();
}
set
{
if (this._aList.getObsCollection() != value)
{
Activate(ActivationPurpose.Write);
this._aList.setObsCollection(value);
}
}
}
public ObservableCollectionEx<Day> DayPoolList
{
get
{
Activate(ActivationPurpose.Read);
return this._dpList.getObsCollection();
}
set
{
if (this._dpList.getObsCollection() != value)
{
Activate(ActivationPurpose.Write);
this._dpList.setObsCollection(value);
}
}
}
public ObservableCollectionEx<Event> EventList
{
get
{
Activate(ActivationPurpose.Read);
return this._eList.getObsCollection();
}
set
{
if (this._eList.getObsCollection() != value)
{
Activate(ActivationPurpose.Write);
this._eList.setObsCollection(value);
}
}
}
public ObservableCollectionEx<Notification> NotificationList
{
get
{
Activate(ActivationPurpose.Read);
return this._nList.getObsCollection();
}
set
{
if (this._nList.getObsCollection() != value)
{
Activate(ActivationPurpose.Write);
this._nList.setObsCollection(value);
}
}
}
public ObservableCollectionEx<Project> ProjectList
{
get
{
Activate(ActivationPurpose.Read);
return this._pList.getObsCollection();
}
set
{
if (this._pList.getObsCollection() != value)
{
Activate(ActivationPurpose.Write);
this._pList.setObsCollection(value);
}
}
}
public ObservableCollectionEx<Reminder> ReminderList
{
get
{
Activate(ActivationPurpose.Read);
return this._rList.getObsCollection();
}
set
{
if (this._rList.getObsCollection() != value)
{
Activate(ActivationPurpose.Write);
this._rList.setObsCollection(value);
}
}
}
#endregion
#region IDataErrorInfo Members
private string m_error = string.Empty;
public string Error
{
set
{
m_error = value;
}
get
{
return m_error;
}
}
public string this[string columnName]
{
get
{
if (columnName == "Alias")
{
if (string.IsNullOrEmpty(Alias))
{
m_error = "Username cannot be empty";
return "Username cannot be empty";
}
}
if (columnName == "Password")
{
if (string.IsNullOrEmpty(Password))
{
m_error = "Password cannot be empty";
return "Password cannot be empty";
}
}
return "";
}
}
#endregion
public void Notify(object o, ObservedItem oType)
{
switch (oType)
{
case ObservedItem.oiNotification:
this._nList.Add((Notification)o);
break;
case ObservedItem.oiReminder:
this._rList.Add((Reminder)o);
break;
default:
break;
}
}
#region IActivatable Members
public void Activate(ActivationPurpose purpose)
{
if (_activator != null)
{
_activator.Activate(purpose);
}
}
public void Bind(IActivator activator)
{
if (_activator == activator)
{
return;
}
if (activator != null && null != _activator)
{
throw new System.InvalidOperationException();
}
_activator = activator;
}
#endregion
}
你看到的代码是我的人类,我在Josh Smits MVVMFoundation的基础上实现了INotifyPropertyChanged。 INotifyPropertyChanged被捕获到DeletableSupport中。这个类使得如果我在我的数据库中删除和对象,删除的标志只是设置为true,而不是永久删除它。
另一个代码是DB4O的一个对象数据库。
以下代码来自我的ViewModel:
public class LoginViewModel : ObservableObject
{
public LoginViewModel(Person person)
{
this.Person = person;
this.LoginCommand = new DelegateCommand<Person>(OnLoginExecuted, CanLoginExecute);
this.ResetCommand = new DelegateCommand<Person>(OnResetExecuted);
this.NewPersonCommand = new DelegateCommand<Person>(OnNewUserExecuted);
this.Person.PropertyChanged += new PropertyChangedEventHandler(LoginViewModel_PersonPropertyChanged);
}
void LoginViewModel_PersonPropertyChanged(object sender, PropertyChangedEventArgs e)
{
//Check after model change if command can be executed
((DelegateCommand<Person>)this.LoginCommand).RaiseCanExecuteChanged();
}
#region Get/Set
public ICommand LoginCommand
{
get;
set;
}
public ICommand ResetCommand
{
get;
set;
}
public ICommand NewPersonCommand
{
get;
set;
}
private Person _person;
public Person Person
{
get
{
return _person;
}
set
{
_person = value;
RaisePropertyChanged("Login_Person");
}
}
private string _error = "";
public string Error
{
get
{
return this._error;
}
set
{
this._error = value;
RaisePropertyChanged("Login_Error");
}
}
#endregion
void OnNewUserExecuted(Person p)
{
//Goto new user screen
}
void OnLoginExecuted(Person person)
{
if (person.Password != "Test" && person.Alias != "tce")
{
this.Error = "Incorrect login";
}
else
{
this.Error = "";
}
}
bool CanLoginExecute(Person person)
{
return this.Person.Alias != "" && this.Person.Password != "";
}
void OnResetExecuted(Person p)
{
p.Alias = string.Empty;
p.Password = string.Empty;
}
}
最终我的XAML。
<UserControl x:Class="GTV.Modules.Views.LoginView.View.LoginView"
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:local="clr-namespace:GTV.Modules.Views.LoginView.View"
mc:Ignorable="d">
<Grid Name="MainGrid" Margin="5">
<Grid.Resources>
<Style TargetType="Button">
<Setter Property="Margin" Value="5" />
</Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Margin" Value="5"/>
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="True">
<TextBlock DockPanel.Dock="Right" Foreground="Red"
FontSize="14" FontWeight="Bold">!</TextBlock>
<Border BorderBrush="Red" BorderThickness="1">
<AdornedElementPlaceholder></AdornedElementPlaceholder>
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors).CurrentItem.ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<Border BorderBrush="Black" BorderThickness="1" CornerRadius="10">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Target="{Binding ElementName=Alias}" >
_Username:
</Label>
<TextBox Grid.Row="0" Grid.Column="1"
Name="Alias"
Text="{Binding Path=Person.Alias, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay,ValidatesOnDataErrors=True}"/>
<Label Grid.Row="1" Grid.Column="0" Target="{Binding ElementName=Password}" >
_Password:
</Label>
<TextBox Grid.Row="1" Grid.Column="1"
Name="Password"
Text="{Binding Path=Person.Password,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay,ValidatesOnDataErrors=True}"/>
<TextBlock Grid.ColumnSpan="2" Grid.Row="4" Text="{Binding Path=Error,Mode=TwoWay}" Foreground="Red"></TextBlock>
<Button Command="{Binding Path=LoginCommand}"
CommandParameter="{Binding Path=Person}"
Grid.Column="0" Grid.Row="2"
>Login</Button>
<Button Command="{Binding Path=ResetCommand}"
CommandParameter="{Binding Path=Person}"
Grid.Column="1" Grid.Row="2"
>Reset</Button>
<Button Command="{Binding Path=NewPersonCommand}"
Grid.Column="1" Grid.Row="3"
>New user</Button>
</Grid>
</Border>
</Grid></UserControl>
XAML.cs看起来像这样:
public partial class LoginView : UserControl, IView
{
public LoginView()
{
InitializeComponent();
MainGrid.DataContext = new LoginViewModel(new Person()
{
Alias = "Enter username",
Password = "123"
});
;
}
public LoginViewModel ViewModel
{
get
{
return this.DataContext as LoginViewModel;
}
}
}
我的问题是,当我按下重置按钮时,我的viewmodel中的Person属性会更新并通知更改,但我的文本框中的文本不会更新。
我有一个示例模块,它可以工作,我似乎无法找到我的问题。 (http://blog.projectsoftware.ro/2009/09/wpf-login-demo-with-mvvm-pattern-update/)
任何人都知道我做错了什么......我将示例转换为4.0并且它仍在工作......它让我疯了,说实话......
提前非常感谢!
答案 0 :(得分:2)
您的SurName和Name属性中似乎缺少对RaisePropertyChanged(Person.Properties.<Name>);
的调用。
更新:
在澄清和第二次看之后,问题似乎是Person中的Properties类。它必须是这样的:
public class Properties
{
public const string Name = "Name";
public const string SurName = "SurName";
public const string Alias = "Alias";
public const string Password = "Password";
}
我删除了“Person_”前缀,因此consts包含属性名称