question

Anja-7727 avatar image
0 Votes"
Anja-7727 asked PeterFleischer-3316 edited

Wpf Mvvm make an instance of NewCategory when createing a new Category

Hi,
I have a window/usercontrol, where I want to make a new Category. So I have some controls (textbox, checkbox and so on), when writing in the first textcontrol, I want to make an instance of a NewCategory in the viewmodel, so when clicking on the save button I can save that instance NewCategory.

My problem is it doesn't make a instance of NewCategory.I go into the saveChangesNew but the NewCategory is still null.

What I'm doing wrong?

Best regards
Simsen :-)

 <UserControl x:Class="Views.Account.AccountObsoleteViewCategoryNew"
              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:Views.Account"
              xmlns:viewModel = "clr-namespace:ViewModel.Account;assembly=ViewModel"
              mc:Ignorable="d" 
              d:DesignHeight="450" d:DesignWidth="800">
     <Grid Grid.Row="0" Grid.Column="1">
         <Grid.RowDefinitions>
             <RowDefinition Height="465" />
         </Grid.RowDefinitions>
         <Grid.ColumnDefinitions>
             <ColumnDefinition Width="489" />
         </Grid.ColumnDefinitions>
         <!--Række 0 meddelse-->
         <StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="0" Width="480">
             <Label x:Name="LblMessageCategoryActive" Content="" BorderThickness="1" Height="50" />
         </StackPanel>
         <!--Række 1 med Ny knappe-->
         <Grid Grid.Row="2" Grid.Column="0" VerticalAlignment="Top" HorizontalAlignment="Right" Height="250">
    
             <Grid.RowDefinitions>
                 <RowDefinition Height="5" />
                 <RowDefinition Height="35" />
                 <RowDefinition Height="35" />
                 <RowDefinition Height="35" />
                 <RowDefinition Height="35" />
                 <RowDefinition Height="45" />
                 <RowDefinition Height="55" />
                 <RowDefinition Height="35" />
                 <RowDefinition Height="200" />
             </Grid.RowDefinitions>
             <Grid.ColumnDefinitions>
                 <ColumnDefinition Width="5" />
                 <ColumnDefinition Width="163" />
                 <ColumnDefinition Width="183" />
             </Grid.ColumnDefinitions>
             <!--Row 1-->
             <Label x:Name="LblMessage" Content="" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" />
    
             <!--Row 2-->
             <Rectangle Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2"  Style="{StaticResource Row1}" />
             <Label Content="Navn:" Grid.Row="2" Grid.Column="1" HorizontalContentAlignment="Right" />
             <TextBox x:Name="TxtCategoryActiveNameNew" Margin="0 0 8 0" Text="{Binding Path=NewCategory, Mode=TwoWay, UpdateSourceTrigger=Explicit}" Grid.Row="2" Grid.Column="2" Height="25" />
    
             <!--Row 3-->
             <Rectangle Grid.Row="3" Grid.Column="1"  Style="{StaticResource Row2}" Grid.ColumnSpan="2" />
             <CheckBox x:Name="CbxCategoryActiveGlobalNew" Content="Global:" Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2" Margin="0 0 168 0" 
                       VerticalAlignment="Center"  HorizontalContentAlignment="Left" />
    
             <!--Row 4-->
             <Rectangle Grid.Row="4" Grid.Column="1"  Style="{StaticResource Row1}" Grid.ColumnSpan="2" />
             <CheckBox x:Name="CbxCategoryActiveActiveNew" Content="Inaktiv:" Grid.Row="4" Grid.Column="1" Margin="0 0 168 0" VerticalAlignment="Center"  
                                       HorizontalContentAlignment="Left" Grid.ColumnSpan="2" />
    
             <!--Row 5 -->
             <Rectangle Grid.Row="5" Grid.Column="1"  Style="{StaticResource Row2}" Grid.ColumnSpan="2" />
             <Label Content="Project:" Grid.Row="5" Grid.Column="1" HorizontalContentAlignment="Right" />
             <ComboBox x:Name="CbxProjectCategoryActiveNew" Grid.Row="5" Grid.Column="2" HorizontalContentAlignment="Left"  VerticalContentAlignment="Center"
                                       ItemsSource="{Binding Path=Projects_GetActive}" DisplayMemberPath="ProjectName" 
                                       SelectedValuePath="ProjectId" 
                                       Text="{Binding ElementName=LivCategories, Path=SelectedValue.ProjectName, Mode=TwoWay}"
                                       SelectedValue="{Binding Path=SelectedValue.ProjectId, Mode=TwoWay}">
             </ComboBox>
             <!--Row 6-->
             <Grid Grid.Row="6" Grid.Column="0" Grid.ColumnSpan="3">
                 <Grid.RowDefinitions>
                     <RowDefinition Height="10" />
                     <RowDefinition Height="35" />
                 </Grid.RowDefinitions>
                 <Grid.ColumnDefinitions>
                     <ColumnDefinition Width="200" />
                     <ColumnDefinition Width="10" />
                     <ColumnDefinition Width="200" />
                 </Grid.ColumnDefinitions>
                 <Button x:Name="BtnNewCancel" Content="Fortryd" Width="150" Grid.Column="0" Grid.Row="1" 
                     HorizontalAlignment="Center" HorizontalContentAlignment="Center" Click="BtnNewCancel_Click"  />
                 <Button x:Name="BtnNewCategorySave" Content="Gem" Width="150" Grid.Column="2" Grid.Row="1" 
                     HorizontalAlignment="Left" HorizontalContentAlignment="Center" Click="BtnNewCategorySave_Click"
                       Command="{Binding CmdSaveNew}"  />
             </Grid>
                
               
         </Grid>
     </Grid>
 </UserControl>

My ViewModel
using System.Collections.Generic;
using Model.Account;
using DAL.Account;
using System.Linq;
using Model.Projects;
using DAL.Projects;
using System.ComponentModel;
using System.Windows.Input;

 namespace ViewModel.Account
 {
     public class CategoryViewModel
     {
         public CategoryViewModel()
         {
             LoadCategories();
             LoadProjects();
             CmdReset = new MyICommand(ResetFields);
             CmdSave = new MyICommand(SaveChanges);
             CmdSaveNew = new MyICommand(SaveChangesNew);
         }
    
         #region New
         public MyICommand CmdReset { get; set; }
         private void ResetFields()
         {
             SelectedCategory.CategoryId = 0;
         }
         #endregion
    
         #region Get
         public List<Category> Categories_GetAll { get; set; }
         public List<Category> Categories_GetActive { get; set; }
         public List<Category> Categories_GetInactive { get; set; }
    
         public void LoadCategories()
         {
             DalCategory dalCategory = new DalCategory();
             var categories = dalCategory.GetCategories();
    
             if (categories != null)
             {
                 //All
                 Categories_GetAll = categories;
    
                 //Active
                 Categories_GetActive = categories.Where(x => x.CategoryIsObsolete == false).ToList();
    
                 //Inactive
                 Categories_GetInactive = categories.Where(x => x.CategoryIsObsolete == true).ToList();
             }
         }
    
         public List<Project> Projects_GetActive { get; set; }
    
         public void LoadProjects()
         {
             DalProjects dalProjects = new DalProjects();
             var projects = dalProjects.GetProjects();
    
             if (projects != null)
             {
                 //Active
                 Projects_GetActive = projects.Where(x => x.ProjectIsActive == true).ToList();
             }
         }
         #endregion
    
         #region Set
         public MyICommand CmdSave { get; set; }
         public void SaveChanges()
         {
             if (SelectedCategory != null)
             {
                 if (SelectedCategory.CategoryId == 0)
                 {
                     //Ny
                     string test = SelectedCategory.CategoryName;
                 }
                 else
                 {
                     //Ret
                     string test = SelectedCategory.CategoryName;
                 }
             }
             if (NewCategory != null)
             {
                 string test = "ok";
             }
         }
    
         public MyICommand CmdSaveNew { get; set; }
         public void SaveChangesNew()
         {
             if (NewCategory != null)
             {
                 string test = "ok";
             }
         }
         #endregion
    
         #region Delete
         public MyICommand DeleteCommand { get; set; }
         private void OnDelete()
         {
             Category cat = SelectedCategory;
             int id = cat.CategoryId;
             int pid = cat.ProjectId;
             string projectName = cat.ProjectName;
             int projectId = cat.ProjectId;
             string catname = cat.CategoryName;
             bool catGlobal = cat.CategoryIsGlobal;
             bool catActive = cat.CategoryIsObsolete;
             string test = "";
             //Categories_GetActive.Remove(SelectedCategory);
         }
    
         private bool CanDelete()
         {
             return SelectedCategory != null;
         }
         #endregion
    
         #region SelectedItem
         private Category _newCategory;
         public Category NewCategory
         {
             get
             {
                 return _newCategory;
             }
    
             set
             {
                 _newCategory = value;
                 OnPropertyChanged("NewCategory");
             }
         }
    
         private Category _selectedCategory;
    
         public Category SelectedCategory
         {
             get
             {
                 return _selectedCategory;
             }
    
             set
             {
                 _selectedCategory = value;
                 OnPropertyChanged("SelectedCategory");
             }
         }
         #endregion
    
         #region INotifyPropertyChanged Members
         public event PropertyChangedEventHandler PropertyChanged;
    
         public void OnPropertyChanged(string propertyName)
         {
             PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
         }
         #endregion
     }
 }
windows-wpf
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Anja-7727 avatar image
0 Votes"
Anja-7727 answered

I give up. I make it instead reading each single value into the viewmodel

 <TextBox x:Name="TxtCategoryActiveNameNew" Margin="0 0 8 0"
                    Text="{Binding CategoryName}"  Grid.Row="2" Grid.Column="2" Height="25" />

And get in the viewmodel with this

 public string CategoryName { get; set; }


5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

PeterFleischer-3316 avatar image
0 Votes"
PeterFleischer-3316 answered PeterFleischer-3316 edited

Hi Anja,
i would change the concept. In the ViewModel add a property CategoryView of the type Category and then bind the UI to this property. At the beginning a new instance is assigned and after each save a new instance is assigned again.

Classes:

 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
 using System.Linq;
 using System.Windows;
 using System.Windows.Input;
    
 namespace WpfApp040
 {
   public class CategoryViewModel : INotifyPropertyChanged
   {
     public string Test { get; set; } = "VM test";
     public CategoryViewModel()
     {
       LoadCategories();
       LoadProjects();
       CmdReset = new MyICommand(ResetFields);
       CmdSave = new MyICommand(SaveChanges);
       CmdSaveNew = new MyICommand(SaveChangesNew);
     }
    
     #region New
     public MyICommand CmdReset { get; set; }
     private void ResetFields(object parameter) => CategoryView = new Category();
     #endregion
    
    #region new
     public MyICommand CmdSaveNew { get; set; }
     public void SaveChangesNew(object parameter)
     {
       // save new Category
       var x = CategoryView;
       ResetFields(null);
     }
     #endregion
    
     #region Get
     public List<Category> Categories_GetAll { get; set; }
     public List<Category> Categories_GetActive { get; set; }
     public List<Category> Categories_GetInactive { get; set; }
    
     public void LoadCategories()
     {
       DalCategory dalCategory = new DalCategory();
       var categories = dalCategory.GetCategories();
    
       if (categories != null)
       {
         //All
         Categories_GetAll = categories;
    
         //Active
         Categories_GetActive = categories.Where(x => x.CategoryIsObsolete == false).ToList();
    
         //Inactive
         Categories_GetInactive = categories.Where(x => x.CategoryIsObsolete == true).ToList();
       }
     }
    
     public List<Project> Projects_GetActive { get; set; }
    
     public void LoadProjects()
     {
       DalProjects dalProjects = new DalProjects();
       var projects = dalProjects.GetProjects();
    
       if (projects != null)
       {
         //Active
         Projects_GetActive = projects.Where(x => x.ProjectIsActive == true).ToList();
       }
     }
     #endregion
    
     #region Set
     public MyICommand CmdSave { get; set; }
     public void SaveChanges(object parameter)
     {
       if (SelectedCategory != null)
       {
         if (SelectedCategory.CategoryId == 0)
         {
           //Ny
           string test = SelectedCategory.CategoryName;
         }
         else
         {
           //Ret
           string test = SelectedCategory.CategoryName;
         }
       }
       //if (NewCategory != null)
       //{
       //  string test = "ok";
       //}
     }
     #endregion
    
     #region Delete
     public MyICommand DeleteCommand { get; set; }
     private void OnDelete()
     {
       Category cat = SelectedCategory;
       int id = cat.CategoryId;
       int pid = cat.ProjectId;
       string projectName = cat.ProjectName;
       int projectId = cat.ProjectId;
       string catname = cat.CategoryName;
       bool catGlobal = cat.CategoryIsGlobal;
       bool catActive = cat.CategoryIsObsolete;
       string test = "";
       //Categories_GetActive.Remove(SelectedCategory);
     }
    
     private bool CanDelete() => SelectedCategory != null;
     #endregion
    
     #region SelectedItem
     private Category _categoryView = new Category();
     public Category CategoryView
     {
       get => _categoryView;
       set
       {
         _categoryView = value;
         OnPropertyChanged(nameof(CategoryView));
       }
     }
    
     private Category _selectedCategory;
    
     public Category SelectedCategory
     {
       get => _selectedCategory;
       set
       {
         _selectedCategory = value;
         OnPropertyChanged("SelectedCategory");
       }
     }
     #endregion
    
     #region INotifyPropertyChanged Members
     public event PropertyChangedEventHandler PropertyChanged;
     public void OnPropertyChanged(string propertyName) =>
       PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
     #endregion
   }
    
   public class Category
   {
     public int CategoryId { get; set; }
     public int ProjectId { get; set; }
     public string ProjectName { get; set; }
     public string CategoryName { get; set; }
     public bool CategoryIsGlobal { get; set; }
     public bool CategoryIsObsolete { get; set; }
   }
    
   public class Project
   {
     public bool ProjectIsActive { get; set; }
   }
    
   internal class DalCategory
   {
     internal List<Category> GetCategories()
     {
       return new List<Category>();
     }
   }
    
   internal class DalProjects
   {
     internal List<Project> GetProjects()
     {
       return new List<Project>();
     }
   }
    
   public class MyICommand : ICommand
   {
     private readonly Predicate<object> _canExecute;
     private readonly Action<object> _action;
     public MyICommand(Action<object> action) { _action = action; _canExecute = null; }
     public MyICommand(Action<object> action, Predicate<object> canExecute) { _action = action; _canExecute = canExecute; }
     public void Execute(object o) => _action(o);
     public bool CanExecute(object o) => _canExecute == null ? true : _canExecute(o);
     public event EventHandler CanExecuteChanged
     {
       add { CommandManager.RequerySuggested += value; }
       remove { CommandManager.RequerySuggested -= value; }
     }
   }
 }


XAML of UserControl:

 <UserControl x:Class="WpfControlLibrary1.Window040UC1"
              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:WpfControlLibrary1"
              mc:Ignorable="d" 
              d:DesignHeight="450" d:DesignWidth="800">
   <UserControl.Resources>
     <Style x:Key="Row1"/>
     <Style x:Key="Row2"/>
   </UserControl.Resources>
   <Grid Grid.Row="0" Grid.Column="1">
     <Grid.RowDefinitions>
       <RowDefinition Height="465" />
     </Grid.RowDefinitions>
     <Grid.ColumnDefinitions>
       <ColumnDefinition Width="489" />
     </Grid.ColumnDefinitions>
     <!--Række 0 meddelse-->
     <StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="0" Width="480">
       <Label x:Name="LblMessageCategoryActive" Content="" BorderThickness="1" Height="50" />
     </StackPanel>
     <Label Content="{Binding Test}"/>
     <!--Række 1 med Ny knappe-->
     <Grid Grid.Row="0"
           VerticalAlignment="Top" HorizontalAlignment="Right">
       <Grid.RowDefinitions>
         <RowDefinition Height="auto"/>
         <RowDefinition Height="auto"/>
       </Grid.RowDefinitions>
       <Grid Grid.Row="0" DataContext="{Binding CategoryView}">
         <Grid.RowDefinitions>
           <RowDefinition Height="5" />
           <RowDefinition Height="35" />
           <RowDefinition Height="35" />
           <RowDefinition Height="35" />
           <RowDefinition Height="35" />
           <RowDefinition Height="45" />
         </Grid.RowDefinitions>
         <Grid.ColumnDefinitions>
           <ColumnDefinition Width="5" />
           <ColumnDefinition Width="163" />
           <ColumnDefinition Width="183" />
         </Grid.ColumnDefinitions>
         <!--Row 1-->
         <Label x:Name="LblMessage" Content="" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" />
    
         <!--Row 2-->
         <Rectangle Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2"  Style="{StaticResource Row1}" />
         <Label Content="Navn:" Grid.Row="2" Grid.Column="1" HorizontalContentAlignment="Right" />
         <TextBox Grid.Row="2" Grid.Column="2" Height="25" Margin="0 0 8 0" 
                  Text="{Binding Path=CategoryName}"/>
    
         <!--Row 3-->
         <Rectangle Grid.Row="3" Grid.Column="1"  Style="{StaticResource Row2}" Grid.ColumnSpan="2" />
         <CheckBox Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2" Margin="0 0 168 0"  
                   VerticalAlignment="Center" HorizontalContentAlignment="Left" 
                   Content="Global:"
                   IsChecked="{Binding CategoryIsGlobal, Mode=TwoWay}"/>
    
         <!--Row 4-->
         <Rectangle Grid.Row="4" Grid.Column="1"  Style="{StaticResource Row1}" Grid.ColumnSpan="2" />
         <CheckBox Grid.Row="4" Grid.Column="1" Grid.ColumnSpan="2" Margin="0 0 168 0"  
                   VerticalAlignment="Center" HorizontalContentAlignment="Left"
                   Content="Inaktiv:"/>
    
         <!--Row 5 -->
         <Rectangle Grid.Row="5" Grid.Column="1"  Style="{StaticResource Row2}" Grid.ColumnSpan="2" />
         <Label Content="Project:" Grid.Row="5" Grid.Column="1" HorizontalContentAlignment="Right" />
         <ComboBox x:Name="CbxProjectCategoryActiveNew" Grid.Row="5" Grid.Column="2" 
                   HorizontalContentAlignment="Left"  VerticalContentAlignment="Center"
                   ItemsSource="{Binding Path=DataContext.Projects_GetActive, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" 
                   DisplayMemberPath="ProjectName" 
                   SelectedValuePath="ProjectId" 
                   Text="{Binding ElementName=LivCategories, Path=SelectedValue.ProjectName, Mode=TwoWay}"/>
       </Grid>
       <!--Row 6-->
       <Grid Grid.Row="1">
         <Grid.RowDefinitions>
           <RowDefinition Height="10" />
           <RowDefinition Height="35" />
         </Grid.RowDefinitions>
         <Grid.ColumnDefinitions>
           <ColumnDefinition Width="200" />
           <ColumnDefinition Width="10" />
           <ColumnDefinition Width="200" />
         </Grid.ColumnDefinitions>
         <Button x:Name="BtnNewCancel" Grid.Column="0" Grid.Row="1" Width="150"
                 HorizontalAlignment="Center" HorizontalContentAlignment="Center"
                 Content="Fortryd"
                 Command="{Binding CmdReset}" />
         <Button x:Name="BtnNewCategorySave" Grid.Column="2" Grid.Row="1"
                 HorizontalAlignment="Left" HorizontalContentAlignment="Center"
                 Content="Gem" Width="150"
                 Command="{Binding CmdSaveNew}"  />
       </Grid>
     </Grid>
   </Grid>
 </UserControl>
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.