WPF - Textbox text doesn't update if source is updated - mvvm

My goal is to create a loginscreen for my users to log in to before entering the application.
I started using PRISM to control my modules, view, viewmodels, etc...
Now my problem is, i have a person class that looks like the folowing:
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
}
The code you see there is my person class, I implements INotifyPropertyChanged on basis of Josh Smits MVVMFoundation. The INotifyPropertyChanged is captured into the DeletableSupport. This class makes it so that if i delete and object in my db, the deleted flag is just set to true, instead of deleting it permantly.
The other code is for DB4O an object-database.
The following code is from my 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;
}
}
And the finaly my 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 looks like this:
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;
}
}
}
My problem is that when i press the reset button, my Person property in my viewmodel gets updated and notifies the change, but the text in my textbox doens't update.
I have an example module where it does work and i can't seem to find my problem.
( http://blog.projectsoftware.ro/2009/09/wpf-login-demo-with-mvvm-pattern-update/ )
Anybody any clue what i'm doing wrong... I converted the example to 4.0 and it is still working.. it drives me insane to be honest...
Big thanks in advance!

It looks like you are missing a call to RaisePropertyChanged(Person.Properties.<Name>); in both your SurName and Name properties.
Update:
After clarification and a second look, the problem seems to be the Properties class inside Person. It has to be like this:
public class Properties
{
public const string Name = "Name";
public const string SurName = "SurName";
public const string Alias = "Alias";
public const string Password = "Password";
}
I removed the "Person_" prefix, so the consts contain exactly the properties names

Related

showing items of picker while consuming web service xamarin

i want to show the items of picker from consuming Restful webservice, but i have an error !
<Picker x:Name="natures" ItemsSource="{Binding Naturee}" SelectedItem="ItemNature"
ItemDisplayBinding="{Binding Name}"
Title="choisir votre nature de dépense"
SelectedIndexChanged="natures_SelectedIndexChanged"/>
my modal PickerModelNature
public class PickerModelNature
{
public class NatureD
{
public string Label;
}
public class ResponseDataN
{
public RootModel Data;
}
public class RootModel : INotifyPropertyChanged
{
List<NatureD> natureList;
[JsonProperty("natureList")]
public List<NatureD> NatureList
{
get { return natureList; }
set
{
if (natureList != value)
{
natureList = value;
OnPropertyChanged();
}
}
}
NatureD itemNature;
public NatureD ItemNature
{
get { return itemNature; }
set
{
if (itemNature != value)
{
itemNature = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var changed = PropertyChanged;
if (changed == null)
return;
changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
and the xaml.cs
public partial class CreerDepense : ContentPage
{
public CreerDepense()
{
InitializeComponent();
this.BindingContext = new RootModel();
GetExpenseNature();
} private async void GetExpenseNature()
{
HttpClient httpClient = new HttpClient();
httpClient.BaseAddress = new Uri("http://192.168.1.6:3000/api/adepApi/GetExpensesNatureList");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await httpClient.GetAsync("http://192.168.1.6:3000/api/adepApi/GetExpensesNatureList");
var content = await response.Content.ReadAsStringAsync();
ResponseDataN EL = JsonConvert.DeserializeObject<ResponseDataN>(content);
// var Items = JsonConvert.DeserializeObject<List<NatureD>>(content);
//listexpense.ItemsSource = Items;
natures.ItemsSource = EL.Data.NatureList;
}
the error is:
Java.Lang.NullPointerException: 'Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference'
what should i do ?

trouble with DataGrid.RowDetailsTemplate to use access command method

the xaml code is:
<DockPanel>
<DataGrid x:Name="Quote" AutoGenerateColumns="False">
<DataGrid.Columns >
<DataGridTextColumn Header="Code" Binding="{Binding Code}"/>
<DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
<DataGridTextColumn Header="Quantities" Binding="{Binding Quantities}"/>
<DataGridTextColumn Header="Price" Binding="{Binding Price}"/>
<DataGridTextColumn Header="Cost" Binding="{Binding Cost}"/>
<DataGridCheckBoxColumn Header="Done" Binding="{Binding Done}"/>
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<Border BorderThickness="0" Background="Beige" Padding="10">
<StackPanel Orientation="Horizontal">
<Button Command="{Binding Path=DataContext.Renew1Command, RelativeSource= {RelativeSource FindAncestor,AncestorType=DataGrid}}">Call Command</Button>
</StackPanel>
</Border>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
</DockPanel>
the model is:
public class StockModel
{
public event PropertyChangedEventHandler PropertyChanged;
public void propChanged(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propName));
}
}
private string code;
public string Code
{
get { return code; }
set
{
code = value;
this.propChanged("Code");
}
}
....
private bool done;
public bool Done
{
get { return done; }
set
{
done = value;
this.propChanged("Done");
}
}
public DelegateCommand Renew1Command;
public void Renew1(object obj)
{
MessageBox.Show("Hello Command");
System.Console.WriteLine("Hello Command");
}
public StockModel()
{
Renew1Command = new DelegateCommand();
this.Renew1Command.ExecuteAction += this.Renew1;
}
}
Finally i init the datasource by:
List<StockModel> stockList = new List<StockModel>();
stockList.Add(new StockModel() { Code = "601919", Cost = "8888", Name = "CIB", Done = true, Price = "16.1", Quantities = "200" });
stockList.Add(new StockModel() { Code = "601919", Cost = "8888", Name = "CIB", Done = false, Price = "16.1", Quantities = "100" });
stockList.Add(new StockModel() { Code = "601919", Cost = "8888", Name = "CIB", Done = true, Price = "16.1", Quantities = "100" });
stockList.Add(new StockModel() { Code = "601919", Cost = "8888", Name = "CIB", Done = true, Price = "16.1", Quantities = "200" });
this.Quote.ItemsSource = stockList;
the DataGridTextColumn can display the data of binding source,
but i can't click button of DataTemplate to call corresponding action from model.
how to fix the binding?
Call Command
move to StockModel class, replace "public DelegateCommand Renew1Command;" with "public DelegateCommand Renew1Command { get; set; }".
the problem will be solved.

GWT : Simple Chat Application for multiple-tab

Sorry for my too long question. I am totally a newbie on GWT and I have still less experiences.I would like to create simple chat application using GWT.
I found for a link simple java chat application using java+servlet+jsp from this. I refrenced it and converted to GWT compactable codes. (I deployed it on http://gwt-chatting-test.appspot.com using GAE). I believe my codes may have plenty of weak points and security holes but I have less experience to handle them .(If you found , pls correct me kindfully).
I would like to describe full of my codes. I used servlet 2.4 , GWT 2.5 ,UI Binder and other required libs.
1) . For Login page
Index.ui.xml
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:d="urn:import:com.google.gwt.dom.client">
<ui:style>
.important {
font-weight: bold;
}
.lblUserName {
margin-right: 3px;
}
</ui:style>
<g:HTMLPanel>
<center>
<g:HorizontalPanel>
<g:Label ui:field="lblUserName" text="User Name : " styleName="{style.lblUserName}"/><g:TextBox height="15px" ui:field="txtUserName"/>
<g:Button styleName="{style.important}" text="Login" ui:field="btnLogin" />
</g:HorizontalPanel>
</center>
</g:HTMLPanel>
Index.java
public class Index extends Composite {
interface IndexUiBinder extends UiBinder<Widget, Index> {}
private static IndexUiBinder uiBinder = GWT.create(IndexUiBinder.class);
#UiField Button btnLogin;
#UiField TextBox txtUserName;
private ChatServiceAsync chatService = GWT.create(ChatService.class);
public Index() {
initWidget(uiBinder.createAndBindUi(this));
}
#UiHandler("btnLogin")
void onClick(ClickEvent e) {
login();
}
#UiHandler("txtUserName")
void onKeyDown(KeyDownEvent event) {
if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
if (txtUserName.getText().trim().length() == 0) {
Window.alert("Enter your name for chat-room !");
}
else {
login();
}
}
}
private void login() {
AsyncCallback<String> callback = new AsyncCallback<String>() {
#Override
public void onSuccess(String result) {
RootPanel.get().clear();
RootPanel.get().add(new Chat());
}
#Override
public void onFailure(Throwable caught) {
System.err.println(caught.getMessage());
}
};
chatService.login(txtUserName.getText(), callback);
}
}
2) . For Chatting Page
Chat.ui.xml
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui">
<ui:style>
.main {
height: 420px;
border: 1px solid silver;
padding: 2px;
width: 620px;
margin-bottom: 5px;
}
.txtInputMsg {
margin-right: 3px;
width : 560px;
height :25px;
}
</ui:style>
<g:HTMLPanel>
<center>
<g:VerticalPanel>
<g:ScrollPanel styleName="{style.main}" height="420px" width="620px" ui:field="pnlMain">
<g:VerticalPanel ui:field="pnlMessage"/>
</g:ScrollPanel>
<g:HorizontalPanel ><g:TextBox styleName="{style.txtInputMsg}" ui:field="txtInputMsg"/><g:Button ui:field="btnLogout" text="Logout"/></g:HorizontalPanel>
</g:VerticalPanel>
</center>
</g:HTMLPanel>
Chat.java
public class Chat extends Composite {
public interface MessageTemlate extends SafeHtmlTemplates {
#Template("<div class =\"{2}\"><div class = \"msgTitle\"> {0}</div><div class=\"msgDescription\">{1}</div></div>")
SafeHtml getFormattedMessage(String name, SafeHtml message, String backgroundColor);
#Template("<div class =\"loginInform\"><span class=\"userName\">{0}</span> has been joined to this conversation !</div>")
SafeHtml notifyLoginUser(String userName);
#Template("<div class =\"logoutInform\"><span class=\"userName\">{0}</span> has been left from this conversation !</div>")
SafeHtml notifyLogoutUser(String userName);
}
private static ChatUiBinder uiBinder = GWT.create(ChatUiBinder.class);
#UiField TextBox txtInputMsg;
#UiField ScrollPanel pnlMain;
#UiField VerticalPanel pnlMessage;
#UiField Button btnLogout;
private static final XMLHttpRequest request = XMLHttpRequest.create();
private static final MessageTemlate TEMPLATES = GWT.create(MessageTemlate.class);
private ChatServiceAsync chatService = GWT.create(ChatService.class);
private String loginUser;
private Timer timer;
interface ChatUiBinder extends UiBinder<Widget, Chat> {}
public Chat() {
initWidget(uiBinder.createAndBindUi(this));
pnlMessage.getElement().setAttribute("style", "width:100%");
initLoginUserName();
request.open("post", URL.encode(GWT.getModuleBaseURL()
+ "chat.do?action=login&time='" + new Date().getTime() + ""));
request.send(null);
}
#UiHandler("txtInputMsg")
void sendMessage(KeyDownEvent event) {
if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
if (txtInputMsg.getText().trim().length() > 0) {
SafeHtml message = SafeHtmlUtils.fromTrustedString(txtInputMsg.getText());
request.open("post", URL.encode(GWT.getModuleBaseURL()
+ "chat.do?action=send&msg=" + message.asString() + "&time='" + new Date().getTime() + ""));
txtInputMsg.setText("");
pnlMessage.add(new HTML(TEMPLATES.getFormattedMessage(loginUser, message, "myMessage")));
pnlMain.scrollToBottom();
txtInputMsg.setFocus(true);
request.send(null);
}
}
}
#UiHandler("btnLogout")
void logout(ClickEvent e) {
boolean confirm = Window.confirm("Are you sure you want to logout now ?");
if (confirm) {
timer.cancel();
request.open("post", URL.encode(GWT.getModuleBaseURL()
+ "chat.do?action=logout&time='" + new Date().getTime() + ""));
request.send(null);
AsyncCallback<String> callback = new AsyncCallback<String>() {
#Override
public void onSuccess(String result) {
RootPanel.get().clear();
RootPanel.get().add(new Index());
}
#Override
public void onFailure(Throwable caught) {
System.err.println(caught.getMessage());
}
};
chatService.logOut(loginUser, callback);
}
}
private void initChatListener() {
timer = new Timer() {
#Override
public void run() {
request.open("post", URL.encode(GWT.getModuleBaseURL()
+ "chat.do?action=get&time='"
+ new Date().getTime() + ""));
request.send(null);
request.setOnReadyStateChange(new ReadyStateChangeHandler() {
#Override
public void onReadyStateChange(XMLHttpRequest xhr) {
if (xhr.getReadyState() == 4) {
if (xhr.getStatus() == 200 && xhr.getResponseText().trim().length() > 1) {
HTML html = new HTML(xhr.getResponseText().trim());
JSONValue value = JSONParser.parseLenient(html.getText());
JSONWrapper json = new JSONWrapper(value);
for (int i = 0; i < json.getValue().isArray().size(); i++) {
String[] chatData = json.get(i).getValue().toString()
.replaceAll("\"", "").split(":");
if (chatData.length >= 3) {
if (chatData[2].equals("login")) {
pnlMessage.add(new HTML(TEMPLATES.notifyLoginUser(chatData[0])));
}
else {
pnlMessage.add(new HTML(TEMPLATES.notifyLogoutUser(chatData[0])));
}
}
else {
pnlMessage.add(new HTML(TEMPLATES.getFormattedMessage(chatData[0],
SafeHtmlUtils.fromTrustedString(chatData[1]), "receivedMessage")
.asString()));
}
pnlMain.scrollToBottom();
}
}
}
}
});
}
};
timer.scheduleRepeating(1000);
}
private void initLoginUserName() {
AsyncCallback<String> callback = new AsyncCallback<String>() {
#Override
public void onSuccess(String result) {
loginUser = result;
if (loginUser == null) {
Window.alert("You need to login !");
RootPanel.get().clear();
RootPanel.get().add(new Index());
}
else {
initChatListener();
}
}
#Override
public void onFailure(Throwable caught) {
System.err.println(caught.getMessage());
}
};
chatService.getUsername(callback);
}
}
3) . Service and ServiceAsync for RPC
ChatService.java
#RemoteServiceRelativePath("chatService")
public interface ChatService extends RemoteService {
String login(String userName);
String getUsername();
String logOut(String username);
}
ChatServiceAsync.java
public interface ChatServiceAsync {
void login(String userName, AsyncCallback<String> callback);
void getUsername(AsyncCallback<String> callback);
void logOut(String username, AsyncCallback<String> callback);
}
4) . Server side control
ChatServiceImpl.java
#SuppressWarnings("serial")
public class ChatServiceImpl extends RemoteServiceServlet implements ChatService {
public String login(final String userName) {
String newUserName = userName;
HttpSession httpSession = getThreadLocalRequest().getSession();
Map<String, List<String>> chat = ChatSupport.getChattingUsers();
synchronized (chat) {
// prevent userName conflict
int i = 1;
while (chat.containsKey(newUserName)) {
++i;
newUserName = userName + "(" + i + ")";
}
chat.put(newUserName, new ArrayList<String>());
}
httpSession.setAttribute("UID", newUserName);
return "LOGIN_SUCCESS";
}
public String logOut(String username) {
// remove the mapping of user name
ChatSupport.getChattingUsers().remove(username);
getThreadLocalRequest().getSession().invalidate();
return "LOGOUT_SUCCESS";
}
public String getUsername() {
// check if there is a HTTP session setup.
HttpSession httpSession = getThreadLocalRequest().getSession(false);
if (httpSession == null) {
return null;
}
// return the user name
return (String) httpSession.getAttribute("UID");
}
}
ChatSupport.java
#SuppressWarnings("serial")
public class ChatSupport extends HttpServlet {
// message map, mapping user UID with a message list
private static Map<String, List<String>> users = new HashMap<String, List<String>>();
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
String action = req.getParameter("action");
if ("login".equals(action)) {
String userName = (String) req.getSession().getAttribute("UID");
for (String key : users.keySet()) {
if (!key.equals(userName)) {
synchronized (users.get(key)) {
users.get(key).add(userName + "::login");
}
}
}
}
else if ("logout".equals(action)) {
String userName = (String) req.getSession().getAttribute("UID");
for (String key : users.keySet()) {
if (!key.equals(userName)) {
synchronized (users.get(key)) {
users.get(key).add(userName + "::logout");
}
}
}
}
// send message
else if ("send".equals(action)) {
// get param with UTF-8 enconding
String msg = new String(req.getParameter("msg").getBytes("ISO-8859-1"), "UTF-8");
String userName = (String) req.getSession().getAttribute("UID");
for (String key : users.keySet()) {
if (!key.equals(userName)) {
synchronized (users.get(key)) {
// put message to any other user's msg list
users.get(key).add(userName + ":" + msg);
}
}
}
}
else if ("get".equals(action)) { // get message
String userName = (String) req.getSession().getAttribute("UID");
if (userName == null) resp.sendError(HttpServletResponse.SC_BAD_REQUEST);
List<String> messages = users.get(userName);
synchronized (messages) {
if (messages.size() > 0) {
// for UTF-8 chars
resp.setCharacterEncoding("UTF-8");
PrintWriter out = resp.getWriter();
JSONArray result = new JSONArray();
// add all msg to json array and clear list
while (messages.size() > 0) {
result.add(messages.remove(0));
}
out.println(result);
out.close();
}
}
}
}
public static Map<String, List<String>> getChattingUsers() {
return users;
}
}
5) . My gwt.xml
....
<module rename-to='testing'>
<inherits name='com.google.gwt.user.User'/>
<inherits name='com.google.gwt.user.theme.clean.Clean'/>
<inherits name="com.google.gwt.http.HTTP" />
<inherits name="com.google.gwt.json.JSON" />
<inherits name="com.pathf.gwt.util.json.jsonwrapper" />
<entry-point class='test.client.TestingEntry'/>
<source path='client'/><source path='shared'/>
</module>
6) . Servlet configurations at web.xml
<servlet>
<servlet-name>chatServlet</servlet-name>
<servlet-class>test.server.ChatServiceImpl</servlet-class>
</servlet>
<servlet>
<servlet-name>ChatServlet</servlet-name>
<servlet-class>test.server.ChatSupport</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ChatServlet</servlet-name>
<url-pattern>/testing/chat.do</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>chatServlet</servlet-name>
<url-pattern>/testing/chatService</url-pattern>
My program was run properly on multiple browsers but can't work on same broswer. I can't run this program by using same brower with multi-tabs. I think I am using same session and I need to create new session for every login. But I have no idea how to create it. From How to get multiple session in single browser , that may causes security problems and I shouldn't. But currently I forgot about securtiy issues.
So , How can I do for multiple-tab browser supports ?

Jenkins plugin development - persistence

I'm still learning plugin dev. This is my first one.
I would like to persist the configuration of my plugin, but it won't work.
Could you please tell me, what am I doing wrong?
I have tried debuging the process, starting from the addition of the plugin to the job 'til the saving of the job config.
I have found, that inside the load() method of the descriptor, no xml file is found!
The path it is looking for is something like: c:\users\Peter\workspace\r-script.\work\whatEverDir\xy.xml
I don't think that the .\ part is causing the config file not to be found, but since it is a Jenkins class generating this path, I would not bet on it. Although the system might have tried to create it here at the first place.
Thanks in advance!
Scriptrunner.jelly
<f:block>
<f:entry title="RScript" field="command">
<f:textarea style="width:99%" />
</f:entry>
</f:block>
<f:entry field="installedPackages" title="Installed packages">
<f:select style="width:40%" />
</f:entry>
<f:entry field="mirrors" title="Choose a mirror">
<f:select style="width:40%" />
</f:entry>
<f:entry>
<f:repeatableProperty field="availablePackages" minimum="1"/>
</f:entry>
AvailablePackage.jelly
<f:entry field="availablePackages">
<f:select style="width:40%" />
<f:repeatableDeleteButton />
</f:entry>
ScriptRunner.java
public class ScriptRunner extends Builder {
private static final String fileExtension = ".R";
private ArrayList<AvailablePackage> availablePackages;
private String command;
private String chosenMirror;
private List<String> mirrorList = new ArrayList<String>();
#DataBoundConstructor
public ScriptRunner(String command, ArrayList<String> installedPackages, ArrayList<String> mirrors, ArrayList<AvailablePackage> availablePackages) {
this.chosenMirror = mirrors.get(0);
this.availablePackages = availablePackages;
this.command = command;
}
public final String getCommand() {
return command;
}
#Override
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher,
BuildListener listener) throws InterruptedException {
return perform(build, launcher, (TaskListener) listener);
}
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher,
TaskListener listener) throws InterruptedException {
FilePath workSpace = build.getWorkspace();
FilePath rScript = null;
if (workSpace == null) {
try {
throw new NoSuchFileException("Workspace could not be set!");
} catch (NoSuchFileException e) {
e.printStackTrace();
}
}
try {
try {
String fullScript;
if (command.contains("options(repos=structure(")) {
fullScript = PackagesManager.singleton().createFullScript(availablePackages, "", command);
} else {
fullScript = PackagesManager.singleton().createFullScript(availablePackages, chosenMirror, command);
}
rScript = workSpace.createTextTempFile("RScriptTemp",
getFileExtension(), fullScript, false);
} catch (IOException e) {
Util.displayIOException(e, listener);
e.printStackTrace(listener.fatalError(Messages
.CommandInterpreter_UnableToProduceScript()));
return false;
}
boolean successfullyRan = false;
try {
EnvVars envVars = build.getEnvironment(listener);
for (Map.Entry<String, String> e : build.getBuildVariables()
.entrySet()) {
envVars.put(e.getKey(), e.getValue());
}
if (launcher.launch().cmds(buildCommandLine(rScript))
.envs(envVars).stdout(listener).pwd(workSpace).join() == 1) {
successfullyRan = true;
}
} catch (IOException e) {
Util.displayIOException(e, listener);
e.printStackTrace(listener.fatalError(Messages
.CommandInterpreter_CommandFailed()));
}
return successfullyRan;
} finally {
try {
if (rScript != null) {
rScript.delete();
}
} catch (IOException e) {
Util.displayIOException(e, listener);
e.printStackTrace(listener.fatalError(Messages
.CommandInterpreter_UnableToDelete(rScript)));
} catch (Exception e) {
e.printStackTrace(listener.fatalError(Messages
.CommandInterpreter_UnableToDelete(rScript)));
}
}
}
public String[] buildCommandLine(FilePath script) {
return new String[] { "Rscript", script.getRemote() };
}
protected String getFileExtension() {
return fileExtension;
}
public List<String> getMirrorList() {
return mirrorList;
}
public void setMirrorList(List<String> mirrorList) {
this.mirrorList = mirrorList;
}
public String getChosenMirror() {
return chosenMirror;
}
public void setChosenMirror(String chosenMirror) {
this.chosenMirror = chosenMirror;
}
public ArrayList<AvailablePackage> getAvailablePackages() {
return availablePackages;
}
#Override
public ScriptBuildStepDescriptorImplementation getDescriptor() {
return (ScriptBuildStepDescriptorImplementation)super.getDescriptor();
}
#Extension
public static class ScriptBuildStepDescriptorImplementation extends
BuildStepDescriptor<Builder> {
private boolean showInstalled;
private String command;
private String chosenMirror;
private ArrayList<AvailablePackage> availablePackages;
public ScriptBuildStepDescriptorImplementation() {
load();
}
#Override
public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
req.bindJSON(this, formData);
save();
return super.configure(req,formData);
}
#Override
public String getDisplayName() {
return "Advanced R script runner";
}
#Override
public boolean isApplicable(Class<? extends AbstractProject> jobType) {
return true;
}
public ListBoxModel doFillInstalledPackagesItems() {
ListBoxModel mirrors = new ListBoxModel();
Set<String> mirrorsList = PackagesManager.singleton()
.getInstalledPackages();
for (String entry : mirrorsList) {
mirrors.add(entry);
}
return mirrors;
}
public ListBoxModel doFillAvailablePackagesItems() {
ListBoxModel packages = new ListBoxModel();
List<String> packageList = PackagesManager.singleton().getAvailablePackages();
Set<String> alreadyInstalled = PackagesManager.singleton().getInstalledPackages();
for (String entry : packageList) {
if (!alreadyInstalled.contains(entry)) {
packages.add(entry);
}
}
return packages;
}
public ListBoxModel doFillMirrorsItems() {
ListBoxModel mirrors = new ListBoxModel();
String[] mirrorsList = MirrorManager.singleton().getMirrors();
int selected = 34;
for (int i = 0; i < mirrorsList.length; i++) {
String[] splitCurrent = mirrorsList[i].split(" - ");
if (chosenMirror != null && chosenMirror.equals(splitCurrent[1])) {
selected = i;
}
mirrors.add(splitCurrent[1], splitCurrent[0]);
}
mirrors.get(selected).selected = true;
return mirrors;
}
public boolean getShowInstalled() {
return showInstalled;
}
public void setShowInstalled(boolean showInstalled) {
this.showInstalled = showInstalled;
}
public String getCommand() {
return command;
}
public void setCommand(String command) {
this.command = command;
}
public String getChosenMirror() {
return chosenMirror;
}
public void setChosenMirror(String chosenMirror) {
this.chosenMirror = chosenMirror;
}
}
}
AvailablePackage.java
public class AvailablePackage extends AbstractDescribableImpl<AvailablePackage> {
private String name;
#DataBoundConstructor
public AvailablePackage(String availablePackages) {
this.name = availablePackages;
}
public String getName() {
return name;
}
#Override
public DescriptorImpl getDescriptor() {
return (DescriptorImpl)super.getDescriptor();
}
#Extension
public static class DescriptorImpl extends Descriptor<AvailablePackage> {
private String name;
public DescriptorImpl() {
load();
}
#Override
public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
req.bindJSON(this, formData);
save();
return super.configure(req,formData);
}
public ListBoxModel doFillAvailablePackagesItems() {
return PackagesManager.singleton().getAvailablePackagesAsListBoxModel(name);
}
#Override
public String getDisplayName() {
return "";
}
public String getName() {
return name;
}
}
}
Sorry for the code formatting! First timer at stackoverflow code posting.
I think you may need to comment this line out
#Override
public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
req.bindJSON(this, formData);
save();
//return super.configure(req,formData);
return true;
}
as it will then save again but with no fields.
A good place to locate Jenkins plugin examples is in https://github.com/jenkinsci

unable to bind data to listbox in windows phone using mvvm architecture

Am trying to bind the data collection from json object from async callback response to the listbox in windows phone through implementing mvvm pattern...I am able to get the data collection to the observablecollectionm<> object but then unable to bind it to UI listbox control in .xaml page.
the following is the code in app.xaml
public static countryListViewModel countrylistVM { get; set; }
Below is code in countries.xaml page.
public Countries()
{
InitializeComponent();
if (App.countrylistVM == null)
App.countrylistVM = new countryListViewModel();
DataContext = App.countrylistVM;
}
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (!App.countrylistVM.IsDataLoaded)
{
App.countrylistVM.Loadcountries();
App.countrylistVM.IsDataLoaded = true;
}
}
the below is code for model.
public class Model: INotifyPropertyChanged
{
private Countriesdata countries;
public Countriesdata Countries
{
get { return countries; }
set
{
if (countries != value)
{
countries = value;
RaisePropertyChanged("Countries");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propname)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propname));
}
}
}
public class Countriesdata : INotifyPropertyChanged
{
private string countryid;
public string Countryid
{
get { return countryid; }
set
{
if (countryid != value)
{
countryid = value;
RaisePropertyChanged("Countryid");
}
}
}
private string countryname;
public string Countryname
{
get { return countryname; }
set
{
if (countryname != value)
{
countryname = value;
RaisePropertyChanged("Countryname");
}
}
}
the following is the code for viewmodel
public class countryListViewModel : INotifyPropertyChanged
{
HttpWebRequest crequest;
HttpWebResponse cresponse;
private bool isDataLoaded = false;
public bool IsDataLoaded
{
get { return isDataLoaded; }
set
{
if (isDataLoaded != value)
{
isDataLoaded = value;
RaisePropertyChanged("IsDataLoaded");
}
}
}
private Countriesdata countries;
public Countriesdata Countries
{
get { return countries; }
set
{
if (countries != value)
{
countries = value;
RaisePropertyChanged("Countries");
}
}
}
private ObservableCollection<Countriesdata> countrylist;
public ObservableCollection<Countriesdata> Countrylist
{
get { return countrylist; }
set
{
if (countrylist != value)
{
countrylist = value;
RaisePropertyChanged("Countrylist");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propname)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propname));
}
public void Loadcountries()
{
try
{
crequest = (HttpWebRequest)WebRequest.Create(serviceurls.getcountries);
crequest.Accept = "application/json";
IAsyncResult cresult = (IAsyncResult)crequest.BeginGetResponse(new AsyncCallback(Responsecallbackcountries), crequest);
}
catch (Exception e)
{
}
}
private void Responsecallbackcountries(IAsyncResult cresult)
{
try
{
string countryresult = string.Empty;
cresponse = (HttpWebResponse)crequest.EndGetResponse(cresult);
using (var Stream = cresponse.GetResponseStream())
{
using (var Reader = new StreamReader(Stream))
{
countryresult = Reader.ReadToEnd();
}
JObject Country = JObject.Parse(countryresult);
JArray Root = (JArray)Country["Countries"];
if (Root.Count != 0)
{
countrylist = new ObservableCollection<Countriesdata>();
var Dictionary = Root.ToDictionary(x => x, x => x);
JToken Tctry;
foreach (var cntry in Dictionary)
{
Tctry = cntry.Value;
countrylist.Add(
new Countriesdata
{
Countryid = Convert.ToString(Tctry["ID"]),
Countryname = Convert.ToString(Tctry["Name"])
});
}
System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
{
Views.Countries vc = new Views.Countries();
});
}
}
}
catch (Exception e)
{
}
}
}
the below is the code for .xaml page.
<ListBox x:Name="lstcountries"
Margin="0,0,-12,0"
ItemsSource="{Binding Countrylist}"
SelectedItem="{Binding Selectedcity, Mode=TwoWay}"
SelectionChanged="lstcountries_SelectionChanged" Background="white">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" Background="Black">
<TextBlock Text="{Binding Countriesdata.Countryid}" Foreground="Black"
Visibility="Collapsed"/>
<TextBlock Text="{Binding Countriesdata.Countryname}" Foreground="Black"
/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Your data template refers to the model, rather than the items in the collection the listbox is being bound to.
Instead, try:
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Countryid}" Visibility="Collapsed"/>
<TextBlock Text="{Binding Countryname}" />
</StackPanel>
</DataTemplate>