Index: /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/AccessAdministrationClient.cs
===================================================================
--- /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/AccessAdministrationClient.cs	(revision 7636)
+++ /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/AccessAdministrationClient.cs	(revision 7637)
@@ -67,4 +67,66 @@
       ExecuteActionAsync(RefreshUserGroups, exceptionCallback);
     }
+    #endregion
+
+    #region Store
+    public void StoreUsers() {
+      foreach (User u in users) {
+        if (u.Modified) {
+          if (u.Id == Guid.Empty) {
+            CallAccessService(s => u.Id = s.AddUser(u).Id);
+          } else {
+            CallAccessService(s => s.UpdateUser(u));
+          }
+          u.SetUnmodified();
+        }
+      }
+    }
+
+    public void StoreUsersAsync(Action<Exception> exceptionCallback) {
+      ExecuteActionAsync(StoreUsers, exceptionCallback);
+    }
+
+    public void StoreUserGroups() {
+      foreach (UserGroup g in Groups) {
+        if (g.Modified) {
+          if (g.Id == Guid.Empty) {
+            CallAccessService(s => g.Id = s.AddUserGroup(g));
+          } else {
+            CallAccessService(s => s.UpdateUserGroup(g));
+          }
+          g.SetUnmodified();
+        }
+      }
+    }
+
+    public void StoreUserGroupsAsync(Action<Exception> exceptionCallback) {
+      ExecuteActionAsync(StoreUserGroups, exceptionCallback);
+    }
+
+    //i don't think such a generic method is a good idea
+    /*public static void Store(IAccessItem item) {
+      
+    } */
+    #endregion
+
+    #region Delete
+    public void DeleteUser(User u) {
+      CallAccessService(s => s.DeleteUser(u));
+    }
+
+    public void DeleteUserAsync(User u, Action<Exception> exceptionCallback) {
+      Action deleteUserAction = new Action(delegate { DeleteUser(u); });
+      ExecuteActionAsync(deleteUserAction, exceptionCallback);
+    }
+
+    public void DeleteUserGroup(UserGroup u) {
+      CallAccessService(s => s.DeleteUserGroup(u));
+    }
+
+    public void DeleteUserGroupAsync(UserGroup u, Action<Exception> exceptionCallback) {
+      Action deleteUserGroupAction = new Action(delegate { DeleteUserGroup(u); });
+      ExecuteActionAsync(deleteUserGroupAction, exceptionCallback);
+    }
+    #endregion
 
     public void ExecuteActionAsync(Action action, Action<Exception> exceptionCallback) {
@@ -86,9 +148,4 @@
         if (ex != null) exceptionCallback(ex);
       }, null);
-    }
-    #endregion
-
-    public static void Store(IAccessItem item) {
-      //TODO: storing
     }
 
Index: /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/Views/RefreshableUserGroupListView.Designer.cs
===================================================================
--- /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/Views/RefreshableUserGroupListView.Designer.cs	(revision 7636)
+++ /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/Views/RefreshableUserGroupListView.Designer.cs	(revision 7637)
@@ -24,11 +24,13 @@
     /// </summary>
     private void InitializeComponent() {
+      System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(RefreshableUserGroupListView));
       this.userGroupListView = new HeuristicLab.Clients.Access.Administration.UserGroupListView();
+      this.storeButton = new System.Windows.Forms.Button();
       this.SuspendLayout();
       // 
       // userGroupListView
       // 
-      this.userGroupListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
-            | System.Windows.Forms.AnchorStyles.Left) 
+      this.userGroupListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+            | System.Windows.Forms.AnchorStyles.Left)
             | System.Windows.Forms.AnchorStyles.Right)));
       this.userGroupListView.Caption = "UserGroupList View";
@@ -40,8 +42,19 @@
       this.userGroupListView.TabIndex = 2;
       // 
+      // storeButton
+      // 
+      this.storeButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.PublishToWeb;
+      this.storeButton.Location = new System.Drawing.Point(33, 3);
+      this.storeButton.Name = "storeButton";
+      this.storeButton.Size = new System.Drawing.Size(24, 24);
+      this.storeButton.TabIndex = 4;
+      this.storeButton.UseVisualStyleBackColor = true;
+      this.storeButton.Click += new System.EventHandler(this.storeButton_Click);
+      // 
       // RefreshableUserGroupListView
       // 
       this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
       this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.storeButton);
       this.Controls.Add(this.userGroupListView);
       this.Name = "RefreshableUserGroupListView";
@@ -49,4 +62,5 @@
       this.Controls.SetChildIndex(this.userGroupListView, 0);
       this.Controls.SetChildIndex(this.refreshButton, 0);
+      this.Controls.SetChildIndex(this.storeButton, 0);
       this.ResumeLayout(false);
 
@@ -56,4 +70,5 @@
 
     private UserGroupListView userGroupListView;
+    private System.Windows.Forms.Button storeButton;
 
   }
Index: /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/Views/RefreshableUserGroupListView.cs
===================================================================
--- /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/Views/RefreshableUserGroupListView.cs	(revision 7636)
+++ /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/Views/RefreshableUserGroupListView.cs	(revision 7637)
@@ -37,4 +37,7 @@
         base.Content_Refreshing(sender, e);
         userGroupListView.Enabled = false;
+        if (Content.Groups != null) {
+          Content.Groups.ItemsRemoved -= new Collections.CollectionItemsChangedEventHandler<Collections.IndexedItem<UserGroup>>(Groups_ItemsRemoved);
+        }
       }
     }
@@ -47,5 +50,25 @@
         userGroupListView.Enabled = true;
         userGroupListView.Content = Content.Groups;
+        if (Content.Groups != null) {
+          Content.Groups.ItemsRemoved += new Collections.CollectionItemsChangedEventHandler<Collections.IndexedItem<UserGroup>>(Groups_ItemsRemoved);
+        }
       }
+    }
+
+    void Groups_ItemsRemoved(object sender, Collections.CollectionItemsChangedEventArgs<Collections.IndexedItem<UserGroup>> e) {
+      foreach (var u in e.Items) {
+        Content.DeleteUserGroupAsync(u.Value, PluginInfrastructure.ErrorHandling.ShowErrorDialog);
+      }
+    }
+
+    protected override void DeregisterContentEvents() {
+      if (Content.Groups != null) {
+        Content.Groups.ItemsRemoved -= new Collections.CollectionItemsChangedEventHandler<Collections.IndexedItem<UserGroup>>(Groups_ItemsRemoved);
+      }
+      base.DeregisterContentEvents();
+    }
+
+    private void storeButton_Click(object sender, EventArgs e) {
+      Content.StoreUserGroupsAsync(PluginInfrastructure.ErrorHandling.ShowErrorDialog);
     }
   }
Index: /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/Views/RefreshableUserListView.Designer.cs
===================================================================
--- /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/Views/RefreshableUserListView.Designer.cs	(revision 7636)
+++ /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/Views/RefreshableUserListView.Designer.cs	(revision 7637)
@@ -25,4 +25,5 @@
     private void InitializeComponent() {
       this.userListView = new HeuristicLab.Clients.Access.Administration.UserListView();
+      this.storeButton = new System.Windows.Forms.Button();
       this.SuspendLayout();
       // 
@@ -30,6 +31,6 @@
       // 
       this.userListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-                  | System.Windows.Forms.AnchorStyles.Left)
-                  | System.Windows.Forms.AnchorStyles.Right)));
+            | System.Windows.Forms.AnchorStyles.Left)
+            | System.Windows.Forms.AnchorStyles.Right)));
       this.userListView.Caption = "UserList View";
       this.userListView.Content = null;
@@ -40,4 +41,14 @@
       this.userListView.TabIndex = 2;
       // 
+      // storeButton
+      // 
+      this.storeButton.Location = new System.Drawing.Point(33, 3);
+      this.storeButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.PublishToWeb;
+      this.storeButton.Name = "storeButton";
+      this.storeButton.Size = new System.Drawing.Size(24, 24);
+      this.storeButton.TabIndex = 3;
+      this.storeButton.UseVisualStyleBackColor = true;
+      this.storeButton.Click += new System.EventHandler(this.storeButton_Click);
+      // 
       // RefreshableUserListView
       // 
@@ -45,6 +56,8 @@
       this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
       this.Controls.Add(this.userListView);
+      this.Controls.Add(this.storeButton);
       this.Name = "RefreshableUserListView";
       this.Size = new System.Drawing.Size(565, 411);
+      this.Controls.SetChildIndex(this.storeButton, 0);
       this.Controls.SetChildIndex(this.userListView, 0);
       this.Controls.SetChildIndex(this.refreshButton, 0);
@@ -56,4 +69,5 @@
 
     private UserListView userListView;
+    private System.Windows.Forms.Button storeButton;
   }
 }
Index: /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/Views/RefreshableUserListView.cs
===================================================================
--- /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/Views/RefreshableUserListView.cs	(revision 7636)
+++ /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/Views/RefreshableUserListView.cs	(revision 7637)
@@ -37,4 +37,7 @@
         base.Content_Refreshing(sender, e);
         userListView.Enabled = false;
+        if (Content.Users != null) {
+          Content.Users.ItemsRemoved -= new Collections.CollectionItemsChangedEventHandler<Collections.IndexedItem<User>>(Users_ItemsRemoved);
+        }
       }
     }
@@ -47,5 +50,25 @@
         userListView.Enabled = true;
         userListView.Content = Content.Users;
+        if (Content.Users != null) {
+          Content.Users.ItemsRemoved += new Collections.CollectionItemsChangedEventHandler<Collections.IndexedItem<User>>(Users_ItemsRemoved);
+        }
       }
+    }
+
+    protected override void DeregisterContentEvents() {
+      if (Content.Users != null) {
+        Content.Users.ItemsRemoved -= new Collections.CollectionItemsChangedEventHandler<Collections.IndexedItem<User>>(Users_ItemsRemoved);
+      }
+      base.DeregisterContentEvents();
+    }
+
+    void Users_ItemsRemoved(object sender, Collections.CollectionItemsChangedEventArgs<Collections.IndexedItem<User>> e) {
+      foreach (var u in e.Items) {
+        Content.DeleteUserAsync(u.Value, PluginInfrastructure.ErrorHandling.ShowErrorDialog);
+      }
+    }
+
+    private void storeButton_Click(object sender, EventArgs e) {
+      Content.StoreUsersAsync(PluginInfrastructure.ErrorHandling.ShowErrorDialog);
     }
   }
Index: /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/Views/UserGroupView.Designer.cs
===================================================================
--- /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/Views/UserGroupView.Designer.cs	(revision 7636)
+++ /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/Views/UserGroupView.Designer.cs	(revision 7637)
@@ -56,4 +56,5 @@
       this.groupNameTextBox.Size = new System.Drawing.Size(282, 20);
       this.groupNameTextBox.TabIndex = 2;
+      this.groupNameTextBox.TextChanged += new System.EventHandler(this.groupNameTextBox_TextChanged);
       // 
       // idTextBox
@@ -61,4 +62,5 @@
       this.idTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
+      this.idTextBox.Enabled = false;
       this.idTextBox.Location = new System.Drawing.Point(79, 29);
       this.idTextBox.Name = "idTextBox";
Index: /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/Views/UserGroupView.cs
===================================================================
--- /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/Views/UserGroupView.cs	(revision 7636)
+++ /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/Views/UserGroupView.cs	(revision 7637)
@@ -47,4 +47,9 @@
       }
     }
+
+    private void groupNameTextBox_TextChanged(object sender, System.EventArgs e) {
+      if (Content.Name != this.groupNameTextBox.Text)
+        Content.Name = this.groupNameTextBox.Text;
+    }
   }
 }
Index: /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/Views/UserView.Designer.cs
===================================================================
--- /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/Views/UserView.Designer.cs	(revision 7636)
+++ /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/Views/UserView.Designer.cs	(revision 7637)
@@ -50,19 +50,22 @@
       // userNameTextBox
       // 
-      this.userNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
-                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.userNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
+      this.userNameTextBox.Enabled = false;
       this.userNameTextBox.Location = new System.Drawing.Point(72, 3);
       this.userNameTextBox.Name = "userNameTextBox";
       this.userNameTextBox.Size = new System.Drawing.Size(289, 20);
       this.userNameTextBox.TabIndex = 2;
+      this.userNameTextBox.TextChanged += new System.EventHandler(this.userNameTextBox_TextChanged);
       // 
       // fullNameTextBox
       // 
-      this.fullNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
-                  | System.Windows.Forms.AnchorStyles.Right)));
+      this.fullNameTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
+            | System.Windows.Forms.AnchorStyles.Right)));
       this.fullNameTextBox.Location = new System.Drawing.Point(72, 29);
       this.fullNameTextBox.Name = "fullNameTextBox";
       this.fullNameTextBox.Size = new System.Drawing.Size(289, 20);
       this.fullNameTextBox.TabIndex = 3;
+      this.fullNameTextBox.TextChanged += new System.EventHandler(this.fullNameTextBox_TextChanged);
       // 
       // UserView
Index: /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/Views/UserView.cs
===================================================================
--- /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/Views/UserView.cs	(revision 7636)
+++ /branches/ClientUserManagement/HeuristicLab.Clients.Access.Administration/3.3/Views/UserView.cs	(revision 7637)
@@ -47,4 +47,14 @@
       }
     }
+
+    private void fullNameTextBox_TextChanged(object sender, System.EventArgs e) {
+      if (Content.FullName != fullNameTextBox.Text)
+        Content.FullName = fullNameTextBox.Text;
+    }
+
+    private void userNameTextBox_TextChanged(object sender, System.EventArgs e) {
+      if (Content.UserName != userNameTextBox.Text)
+        Content.UserName = userNameTextBox.Text;
+    }
   }
 }
Index: /branches/ClientUserManagement/HeuristicLab.Clients.Access/3.3/ServiceClients/AccessItem.cs
===================================================================
--- /branches/ClientUserManagement/HeuristicLab.Clients.Access/3.3/ServiceClients/AccessItem.cs	(revision 7636)
+++ /branches/ClientUserManagement/HeuristicLab.Clients.Access/3.3/ServiceClients/AccessItem.cs	(revision 7637)
@@ -65,4 +65,8 @@
     }
 
+    public void SetUnmodified() {
+      Modified = false;
+    }
+
     protected AccessItem(AccessItem original, Cloner cloner) {
       cloner.RegisterClonedObject(original, this);
Index: /branches/ClientUserManagement/HeuristicLab.Clients.Access/3.3/ServiceClients/UserGroup.cs
===================================================================
--- /branches/ClientUserManagement/HeuristicLab.Clients.Access/3.3/ServiceClients/UserGroup.cs	(revision 7636)
+++ /branches/ClientUserManagement/HeuristicLab.Clients.Access/3.3/ServiceClients/UserGroup.cs	(revision 7637)
@@ -20,10 +20,12 @@
 #endregion
 
+using System;
 using System.Drawing;
+using System.Runtime.Serialization;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
 namespace HeuristicLab.Clients.Access {
   [Item("UserGroup", "A group.")]
-  public partial class UserGroup {
+  public partial class UserGroup : IDisposable {
     protected UserGroup(UserGroup original, Cloner cloner)
       : base(original, cloner) {
@@ -35,5 +37,19 @@
     }
 
-    public UserGroup() { }
+    public UserGroup() {
+      this.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(UserGroup_PropertyChanged);
+    }
+
+    [OnDeserialized]
+    private void RegisterNamePropertyChangedEvent(StreamingContext c) {
+      this.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(UserGroup_PropertyChanged);
+    }
+
+    void UserGroup_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) {
+      //this is a workaround as we can't overide the Name property and fire directly 
+      if (e.PropertyName == "Name") {
+        OnToStringChanged();
+      }
+    }
 
     public override IDeepCloneable Clone(Cloner cloner) {
@@ -44,4 +60,10 @@
       return Name;
     }
+
+    #region IDisposable Members
+    public void Dispose() {
+      this.PropertyChanged -= new System.ComponentModel.PropertyChangedEventHandler(UserGroup_PropertyChanged);
+    }
+    #endregion
   }
 }
Index: /branches/ClientUserManagement/HeuristicLab.Services.Access/3.3/AccessService.cs
===================================================================
--- /branches/ClientUserManagement/HeuristicLab.Services.Access/3.3/AccessService.cs	(revision 7636)
+++ /branches/ClientUserManagement/HeuristicLab.Services.Access/3.3/AccessService.cs	(revision 7637)
@@ -644,6 +644,7 @@
     public Guid AddUserGroup(DT.UserGroup group) {
       using (DA.AccessServiceDataContext context = new DA.AccessServiceDataContext()) {
-        //because id is not automatically set because of user, we have to do it here manually for group
+        //because id is not automatically set because of user, we have to do it here manually for group   
         group.Id = Guid.NewGuid();
+
         context.UserGroupBases.InsertOnSubmit(Convert.ToEntity(group));
         context.SubmitChanges();
@@ -653,13 +654,25 @@
 
     public void UpdateUserGroup(DT.UserGroup group) {
-      AddUserGroup(group);
+      using (DA.AccessServiceDataContext context = new DA.AccessServiceDataContext()) {
+        DA.UserGroup entity = context.UserGroupBases.OfType<DA.UserGroup>().FirstOrDefault(x => x.Id == group.Id);
+        Convert.ToEntity(group, entity);
+        context.SubmitChanges();
+      }
     }
 
     public void DeleteUserGroup(DT.UserGroup group) {
       RoleVerifier.AuthenticateForAllRoles(AccessServiceRoles.Administrator);
-
-      using (DA.AccessServiceDataContext context = new DA.AccessServiceDataContext()) {
-        context.UserGroupBases.DeleteOnSubmit(Convert.ToEntity(group));
-        context.SubmitChanges();
+      var g = group; //linq does not like vars called group
+
+      using (DA.AccessServiceDataContext context = new DA.AccessServiceDataContext()) {
+        var query = from ug in context.UserGroupBases.OfType<DA.UserGroup>()
+                    where ug.Id == g.Id
+                    select ug;
+        if (query.Count() > 0) {
+          context.UserGroupBases.DeleteOnSubmit(query.First());
+          context.SubmitChanges();
+        } else {
+          throw new Exception("UserGroup with id " + g.Id + " does not exist.");
+        }
       }
     }
Index: /branches/ClientUserManagement/HeuristicLab.Services.Access/3.3/Convert.cs
===================================================================
--- /branches/ClientUserManagement/HeuristicLab.Services.Access/3.3/Convert.cs	(revision 7636)
+++ /branches/ClientUserManagement/HeuristicLab.Services.Access/3.3/Convert.cs	(revision 7637)
@@ -283,4 +283,8 @@
       };
     }
+
+    public static void ToEntity(DT.UserGroup source, DA.UserGroup target) {
+      target.Name = source.Name;
+    }
     #endregion
 
