WPF C# MVVM program not updating ListView - c#

I am working on WPF, MVVM C# simple app for learning.
I do have my front-end having Table kind of structure using element ""
See "VehicalForm.xaml" below.
Below is code of my View as well as View-Model part. (I have given just necessary files. Please let me know if you need any other files)
App.xaml.cs
using Seris.ViewModels;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Windows;
namespace Seris
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
public void OnStartup(object sender, StartupEventArgs e)
{
VehicalForm vehicalForm = new VehicalForm();
vehicalForm.DataContext = new VehicalMainViewModel();
vehicalForm.Show();
}
}
}
VehicalForm.xaml
<Window x:Class="Seris.VehicalForm"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<WrapPanel Orientation="Vertical" Margin="10 " >
<Label Content="Vehical No" HorizontalAlignment="Left"/>
<TextBox Name="VehicalNo_Text" Height="23" TextWrapping="Wrap" Text="TextBox" HorizontalAlignment="Left"/>
<Label Content="Model" HorizontalAlignment="Left"/>
<TextBox Name="Model_Text" Height="23" TextWrapping="Wrap" Text="TextBox" HorizontalAlignment="Left" />
<Label Content="Manufacturing Date" HorizontalAlignment="Left"/>
<DatePicker/>
<Label Content="IU No" HorizontalAlignment="Left"/>
<TextBox Height="23" Name="IUNO_Text" TextWrapping="Wrap" Text="TextBox" HorizontalAlignment="Left"/>
<Label Content="Personnel" HorizontalAlignment="Left"/>
<ComboBox Name="Personnel_Combo" HorizontalAlignment="Left" Width="116"/>
<Separator Height="20" RenderTransformOrigin="0.5,0.5" Width="16"/>
<Button Name="Save_Button" Command="{Binding SaveToList}" Content="Save" Width="66"/>
<ListView Height="294" Width="371" >
<ListView Height="294" Width="371" ItemsSource="{Binding listItems, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" >
<ListView.View>
<GridView>
<GridViewColumn Header="Vehical No" DisplayMemberBinding="{Binding VehicalNo}" />
<GridViewColumn Header="Model" DisplayMemberBinding="{Binding Model}" />
<GridViewColumn Header="ManufacturingDate" DisplayMemberBinding="{Binding ManufacturingDate}" />
<GridViewColumn Header="IUNo" DisplayMemberBinding="{Binding IUNo}" />
<GridViewColumn Header="Personnel" DisplayMemberBinding="{Binding Personnel}" />
</GridView>
</ListView.View>
</ListView>
</WrapPanel>
VehicalForm.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Seris
{
public partial class VehicalForm : Window
{
public VehicalForm()
{
InitializeComponent();
}
}
}
VehicalMainViewModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Seris.Models;
using System.Collections.ObjectModel;
using System.Windows.Input;
using Seris.Commands;
using Seris.ViewModels;
namespace Seris.ViewModels
{
public class VehicalMainViewModel : ObservableObject
{
ObservableCollection<VehicalModel> listItems = new ObservableCollection<VehicalModel>();
#region Getter-Setter
private string _VehicalNo;
public string VehicalNo
{
get { return _VehicalNo; }
set
{
if (value != _VehicalNo)
{
_VehicalNo = value.Trim();
if(OnPropertyChanged("VehicalNo"))
listItems.Add(new VehicalModel(VehicalNo, Model, ManufacturingDate, IUNo, PersonnelName));
}
}
}
private string _Model;
public string Model
{
get { return _Model; }
set
{
if (value != _Model)
{
_Model = value.Trim();
OnPropertyChanged("Model");
}
}
}
private DateTime _ManufacturingDate;
public DateTime ManufacturingDate
{
get { return _ManufacturingDate; }
set
{
if (value != _ManufacturingDate)
{
_ManufacturingDate = value;
OnPropertyChanged("ManufacturingDate");
}
}
}
private string _IUNo;
public string IUNo
{
get { return _IUNo; }
set
{
if (value != _IUNo)
{
_IUNo = value.Trim();
OnPropertyChanged("IUNo");
}
}
}
private string _PersonnelName;
public string PersonnelName
{
get { return _PersonnelName; }
set
{
if (value != _PersonnelName)
{
_PersonnelName = value.Trim();
OnPropertyChanged("PersonnelName");
}
}
}
#endregion
private ICommand _saveButton_Command;
public ICommand SaveButton_Command
{
get { return _saveButton_Command; }
set { _saveButton_Command = value; }
}
public void SaveToList(object o1)
{
listItems.Add(new VehicalModel(VehicalNo,Model,ManufacturingDate,IUNo,PersonnelName));
}
public void RemoveFromList()
{
}
public VehicalMainViewModel()
{
VehicalModel vm=new VehicalModel();
SaveButton_Command = new RelayCommand(new Action<object>(SaveToList));
}
}
}
ObservableObject.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Windows;
namespace Seris.Models
{
public abstract class ObservableObject: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool OnPropertyChanged(string propertyName)
{
this.VerifyPropertyName(propertyName);
PropertyChangedEventHandler handler = PropertyChanged;
if(handler!=null)
{
if (propertyName != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
return true;
}
}
return false;
}
public void VerifyPropertyName(string propertyName)
{
if(TypeDescriptor.GetProperties(this)[propertyName]==null)
{
string msg = "Invalid Property Name: " + propertyName;
if (this.ThrowOnInvalidPropertyName)
throw new Exception(msg);
else
Debug.Fail(msg);
}
}
public bool ThrowOnInvalidPropertyName { get; set; }
}
}
VehicalModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace Seris.Models
{
public class VehicalModel : ObservableObject
{
#region Getter-Setter
private string _VehicalNo;
public string VehicalNo
{
get { return _VehicalNo; }
set
{
if (value != _VehicalNo)
{
_VehicalNo = value.Trim();
OnPropertyChanged("VehicalNo");
}
}
}
private string _Model;
public string Model
{
get { return _Model; }
set
{
if (value != _Model)
{
_Model = value.Trim();
OnPropertyChanged("Model");
}
}
}
private DateTime _ManufacturingDate;
public DateTime ManufacturingDate
{
get { return _ManufacturingDate; }
set
{
if (value != _ManufacturingDate)
{
_ManufacturingDate = value;
OnPropertyChanged("ManufacturingDate");
}
}
}
private string _IUNo;
public string IUNo
{
get { return _IUNo; }
set
{
if (value != _IUNo)
{
_IUNo = value.Trim();
OnPropertyChanged("IUNo");
}
}
}
private string _PersonnelName;
public string PersonnelName
{
get { return _PersonnelName; }
set
{
if (value != _PersonnelName)
{
_PersonnelName = value.Trim();
OnPropertyChanged("PersonnelName");
}
}
}
#endregion
#region Constructor
public VehicalModel(string VehicalNo, string Model, DateTime ManufacturingDate, string IUNo, string PersonnelName)
{
this.VehicalNo = VehicalNo;
this.Model = Model;
this.ManufacturingDate = ManufacturingDate;
this.IUNo = IUNo;
this.PersonnelName = PersonnelName;
}
public VehicalModel()
{
this.VehicalNo = null;
this.Model = null;
this.ManufacturingDate = DateTime.Now;
this.IUNo = null;
this.PersonnelName = null;
}
#endregion
#region Methods
#region Validate Methods
public bool Validate_VehicalNo()
{
if (matchRE(VehicalNo,"[A-Zz-z][A-Zz-z0-9]{6}"))
return true;
else
return false;
}
public bool Validate_Model()
{
if(Model!=null)
return true;
else
return false;
}
public bool Validate_ManufacturingDate()
{
return true;
}
public bool Validate_IUNo()
{
if(matchRE(IUNo,"[0-9]{10}"))
return true;
else
return false;
}
public bool Validate_PersonnelName()
{
if(matchRE(PersonnelName,"[A-Za-z]+"))
return true;
else
return false;
}
public bool matchRE(string stringToMatch, string regularExpression)
{
Regex regex = new Regex(#regularExpression);
Match match = regex.Match(stringToMatch);
if(match.Success)
return(true);
else
return(false);
}
#endregion
#endregion
}
}
What I need is
1) When I update VehicalNo, new row should be added in the table.
2) If I need to update individual elements of every row in future which should reflect in table as soon as I update , is there inbuilt facility in ListView? Or I need to use List for individual elements (i.e. VehicalNo, Model, ... ) and put in one main List keeping eye using ObservableObject?
I don't know eventhough it is being added to list as well as I have implemented INotifyPropert using ObservableObject, why its not reflecting in front-end.
Please help.

Add
public ObservableCollection ListItems {get{return listItems;}}
to you VehicalMainViewModel and change binding to
ItemsSource="{Binding ListItems}"
P.S. your listItems is private field.

ok so heres an example of the first Text box and you can follow suit on the rest:
<Window x:Class="Seris.VehicalForm"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:local="clr-namespace:Seris.ViewModels"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:VehicalMainViewModel/>
</Window.DataContext>
<Label Content="Vehical No" HorizontalAlignment="Left"/>
<TextBox Name="VehicalNo_Text" Height="23" TextWrapping="Wrap" Text="{Binding VehicalNo}" HorizontalAlignment="Left"/>
I cannot find any references at the moment but I would suggest looking at DataContext and Data Binding in WPF
EDIT
<Application x:Class="Seris.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="VehicalForm.xaml">
<Application.Resources>
</Application.Resources>
</Application>

Related

Get value from a Combobox Binding MVVM not get correctly

Hi i made a bindable combobox with MVVM and when i'm trying to get the value of combobox it gets the path of the value ex:I select a name and it return WpfApp1.Parts .
How can i get the name from combobox as string?
And if enyone know how can i save the combobox that when i add a new value , like when i enter again on the program my last entered value to be there!
View.Parts:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
namespace WpfApp1
{
public class Parts : Changed
{
public string name;
public string Name
{
get { return name; }
set
{
if (name != value)
{
name = value;
RaisePropertyChanged("Name");
}
}
}
}
}
ViewModel.AddViewModel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Collections.ObjectModel;
namespace WpfApp1
{
public class AddViewModel : Changed
{
private ObservableCollection<Parts> _persons;
public string names;
public AddViewModel()
{
Persons = new ObservableCollection<Parts>()
{
new Parts{Name="Nirav"}
,new Parts{Name="Kapil"}
,new Parts{Name="Arvind"}
,new Parts{Name="Rajan"}
};
}
public ObservableCollection<Parts> Persons
{
get { return _persons; }
set {
if (_persons != value)
{
_persons = value;
RaisePropertyChanged("Persons");
}
}
}
private Parts _sperson;
public Parts SPerson
{
get { return _sperson; }
set {
if (_sperson != value)
{
_sperson = value;
RaisePropertyChanged("SPerson");
}
}
}
}
}
MainWindow:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApp1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public AddViewModel addviewmodel;
public MainWindow()
{
InitializeComponent();
addviewmodel = new AddViewModel();
DataContext = addviewmodel;
}
public AddViewModel getModel()
{
return addviewmodel;
}
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
//textshow.Text = holo.SelectedItem;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
getModel().Persons.Add(new Parts { Name = cmbtxt.Text});
}
}
}
MainWindowXaml:
<Grid>
<ComboBox x:Name="holo" ItemsSource="{Binding Persons}" SelectedItem="{Binding SPerson}" SelectionChanged="ComboBox_SelectionChanged" HorizontalAlignment="Left" Margin="391,17,0,0" VerticalAlignment="Top" Width="314" Height="27">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Name}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBox Name="cmbtxt" HorizontalAlignment="Left" Height="23" Margin="24,21,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="172" />
<Button Content="Add" HorizontalAlignment="Left" Margin="24,88,0,0" VerticalAlignment="Top" Width="156" Height="49" Click="Button_Click"/>
<TextBlock x:Name="textshow" HorizontalAlignment="Left" Text="{Binding Path=SPerson}" TextWrapping="Wrap" VerticalAlignment="Top" Margin="391,104,0,0" Height="33" Width="223"/>
</Grid>
You should bind to the Name property of the selected item returned by the SPerson property:
<TextBlock x:Name="textshow" HorizontalAlignment="Left"
Text="{Binding Path=SPerson.Name}"
TextWrapping="Wrap" VerticalAlignment="Top"
Margin="391,104,0,0" Height="33" Width="223"/>
What you currently see is the ToString() representation of the Parts class so the other option would to override this method:
public class Parts : Changed
{
public string name;
public string Name
{
get { return name; }
set
{
if (name != value)
{
name = value;
RaisePropertyChanged("Name");
}
}
}
public override string ToString()
{
return name;
}
}
The error is here
<TextBlock x:Name="textshow" HorizontalAlignment="Left" Text="{Binding Path=SPerson}"
You cannot bind Text property to complex Object like Parts you should bind it to the Name as you did with ComboBox

Conditional binding two properties to one Textbox

Hello Dear Programmers
I decided to learn MVVP pattern using C# language. That is why I have one question for you. I have a very simple application which consists of 5 textboxes and one button. It is not finished yet.
What I achieved:
When I write some text in first textbox (Employee Name), dynamic
search launches and all matched records appear in a list.
When I click a record in a list, information appears in textboxes.
What I want to achieve:
When I write some text in first textbox (Employee Name), dynamic
search launches and all matched records appear in a list.
When I click a record in a list, information appears in textboxes.
When I edit first textbox (Employee Name), Employee Name in a list
should not be changed. (Only after button click).
Observations:
I read about Multibinding, Converters and UpdateSourcetrigger: Explicit and Propertychanged. I tried to multibind a textbox TextboxEmployeeName. When I set PropertyChanged, Dynamic search works but Employee Name in a list is changed when I write in Textbox, but when I set Explicit, Employee Name in a list does not change (what I want to achieve) but dynamic search does not work.
My question is: How to set adequate UpdateSourceTrigger according to condition?
If (Record is not selected)
{
UpdateSourceTrigger = PropertyChanged
}
Else If (Record is selected)
{
UpdateSourceTrigger = Explicit
}
I dont know if I take a good way to solve my problem. Maybe you know better solution? Could you help me? Below I placed my entire code:
Employee.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Windows;
using System.Collections.ObjectModel;
using System.Windows.Data;
using System.Windows.Threading;
namespace OneWayTwoWayBinding
{
public class Employee : INotifyPropertyChanged
{
private string employeeName;
private string employeeID;
private int? employeeSalary;
private string employeeDesigner;
private string employeeEmailID;
private Employee selectedEmployee;
private ICollectionView filteredCollection;
private Employee dynamicSearch;
private int changedPathBinding;
public string EmployeeName
{
get
{
//Application.Current.Dispatcher.BeginInvoke(new Action(() => MessageBox.Show(employeeName)));
return employeeName;
}
set
{
employeeName = value;
if (FilteredCollection != null)
FilteredCollection.Filter = x => (String.IsNullOrEmpty(employeeName) || ((Employee)x).EmployeeName.Contains(employeeName));
OnPropertyChanged("EmployeeName");
}
}
public string EmployeeID
{
get
{
return employeeID;
}
set
{
employeeID = value;
OnPropertyChanged("EmployeeID");
}
}
public int? EmployeeSalary
{
get
{
return employeeSalary;
}
set
{
employeeSalary = value;
OnPropertyChanged("EmployeeSalary");
if (FilteredCollection != null)
FilteredCollection.Filter = x => ((employeeSalary == null) || ((Employee)x).EmployeeSalary == employeeSalary);
}
}
public string EmployeeDesigner
{
get
{
//Application.Current.Dispatcher.BeginInvoke(new Action(() => MessageBox.Show(employeeDesigner)));
return employeeDesigner;
}
set
{
employeeDesigner = value;
OnPropertyChanged("EmployeeDesigner");
if (FilteredCollection != null)
FilteredCollection.Filter = x => (String.IsNullOrEmpty(employeeDesigner) || ((Employee)x).EmployeeDesigner.Contains(employeeDesigner));
}
}
public string EmployeeEmailID
{
get
{
return employeeEmailID;
}
set
{
employeeEmailID = value;
OnPropertyChanged("EmployeeEmailID");
}
}
public IList<Employee> EmployeeList
{
get; set;
}
public Employee SelectedEmployee
{
get
{
//Application.Current.Dispatcher.BeginInvoke(new Action(() => MessageBox.Show(selectedEmployee.SelectedEmployee.ToString())));
return selectedEmployee;
}
set
{
selectedEmployee = value;
OnPropertyChanged("SelectedEmployee");
}
}
public Employee DynamicSearch
{
get
{
return dynamicSearch;
}
set
{
dynamicSearch = value;
OnPropertyChanged("DynamicSearch");
//FilteredCollection.Filter = x => (String.IsNullOrEmpty(dynamicSearch.EmployeeName) || ((Employee)x).EmployeeName.Contains(dynamicSearch.EmployeeName));
}
}
public ICollectionView FilteredCollection
{
get
{
return filteredCollection;
}
set
{
filteredCollection = value;
OnPropertyChanged("FilteredCollection");
}
}
public int ChangedPathBinding
{
get
{
//Application.Current.Dispatcher.BeginInvoke(new Action(() => MessageBox.Show(changedPathBinding.ToString())));
return changedPathBinding;
}
set
{
changedPathBinding = value;
OnPropertyChanged("ChangedPathBinding");
//SelectedEmployee.EmployeeName
}
}
public ObservableCollection<Employee> Employees { get; private set; }
public event PropertyChangedEventHandler PropertyChanged = null;
virtual protected void OnPropertyChanged(string propName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}
EmployeeViewModel.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
namespace OneWayTwoWayBinding
{
public class EmployeeViewModel : Employee
{
public EmployeeViewModel()
{
ObservableCollection<Employee> Employees = new ObservableCollection<Employee>()
{
new Employee{EmployeeName = "Adrian",EmployeeID = "1",EmployeeSalary = 15000,EmployeeDesigner = "SoftwareEngingeer12312", EmployeeEmailID = "drozd001#gmail423423.com"},
new Employee{EmployeeName = "Bartek",EmployeeID = "2",EmployeeSalary = 15000,EmployeeDesigner = "SoftwareEngingeer",EmployeeEmailID = "drozd001#gmail.com"},
new Employee{EmployeeName = "Czarek",EmployeeID = "3",EmployeeSalary = 30000,EmployeeDesigner = "SoftwareEngingeer",EmployeeEmailID = "drozd001#gmail.com"}
};
FilteredCollection = CollectionViewSource.GetDefaultView(Employees);
//SelectedEmployee = new Employee {EmployeeName = string.Empty, EmployeeID = string.Empty, EmployeeSalary = string.Empty, EmployeeDesigner = string.Empty, EmployeeEmailID = string.Empty};
//EmployeeDesigner = "SoftwareEngingeer12312";
//EmployeeDesigner = "SoftwareEngingeer12312";
//DynamicSearch.EmployeeName = "Czarek";
//EmployeeSalary = 10;
ChangedPathBinding = -1;
SelectedEmployee = null;
}
RelayCommand _saveCommand;
public ICommand SaveCommand
{
get
{
if (_saveCommand == null)
{
_saveCommand = new RelayCommand((param) => this.Save(param),
param => this.CanSave);
}
return _saveCommand;
}
}
public void Save(object parameter)
{
FilteredCollection.Filter = null;
SelectedEmployee = null;
EmployeeName = null;
EmployeeSalary = null;
}
bool CanSave
{
get
{
return true;
}
}
}
}
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace OneWayTwoWayBinding
{
/// <summary>
/// Logika interakcji dla klasy MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new EmployeeViewModel();
}
}
}
Converters.cs
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
namespace OneWayTwoWayBinding
{
public class Converters : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
//value = 5; //ta liczba pojawi sie w textbox po uruchomieniu aplikacji
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (string.IsNullOrEmpty(value.ToString()))
return null;
//int var;
//var = int.Parse(value.ToString());
//var *= 2;
//value = var;
return value; //liczba wpisana w textbox z poziomu widoku aplikacji
}
}
public class ConverterFiltering : IMultiValueConverter
{
public object Convert(object[] value, Type targetType, object parameter, CultureInfo culture)
{
if (value[0] == DependencyProperty.UnsetValue || value[1] == DependencyProperty.UnsetValue)
{
return value[0];
}
MessageBox.Show("Values[0]: " + value[0].ToString());
//MessageBox.Show("Values[1]: " + value[1].ToString());
return value[0];
}
public object[] ConvertBack(object value, Type[] targetType, object parameter, CultureInfo culture)
{
string[] values = new string[2];
values[0] = value.ToString();
values[1] = value.ToString();
MessageBox.Show("Values[0]: " + values[0].ToString() + " Values[1]: " + values[1].ToString());
return values;
}
}
}
MainWindow.xaml
<Window x:Class="OneWayTwoWayBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:OneWayTwoWayBinding"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<local:Converters x:Key="NullableValueConverter" />
<local:ConverterFiltering x:Key="ConverterFiltering" />
</Window.Resources>
<Grid Margin="0,0,0,20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListView Name="EmployeeListView" HorizontalAlignment="Left" Height="160" Margin="0,259,0,0" VerticalAlignment="Top" Width="792" ItemsSource="{Binding FilteredCollection}" SelectedItem="{Binding SelectedEmployee, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedIndex="{Binding ChangedPathBinding}" >
<ListView.View>
<GridView>
<GridViewColumn Header="EmployeeName" Width="150" DisplayMemberBinding="{Binding EmployeeName}" />
<GridViewColumn Header="EmployeeID" Width="150" DisplayMemberBinding="{Binding EmployeeID}" />
<GridViewColumn Header="EmployeeSalary" Width="150" DisplayMemberBinding="{Binding EmployeeSalary}" />
<GridViewColumn Header="EmployeeDesigner" Width="150" DisplayMemberBinding="{Binding EmployeeDesigner}" />
<GridViewColumn Header="EmployeeEmailID" Width="150" DisplayMemberBinding="{Binding EmployeeEmailID}" />
</GridView>
</ListView.View>
</ListView>
<Label Content="Employee Name" HorizontalAlignment="Left" Margin="15,52,0,0" VerticalAlignment="Top" Width="77" Height="23"/>
<TextBox Name ="TextboxEmployeeName" HorizontalAlignment="Left" Height="23" Margin="97,52,0,0" VerticalAlignment="Top" Width="522" >
<TextBox.Text>
<MultiBinding Converter="{StaticResource ConverterFiltering}" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
<Binding Path="SelectedEmployee.EmployeeName" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" />
<Binding Path="EmployeeName" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"/>
</MultiBinding>
</TextBox.Text>
</TextBox>
<Label Content="Label" HorizontalAlignment="Left" Margin="15,91,0,0" VerticalAlignment="Top" Width="77" Height="23"/>
<TextBox HorizontalAlignment="Left" Height="23" Margin="97,91,0,0" Text="{Binding Path=SelectedEmployee.EmployeeID, Mode=TwoWay}" VerticalAlignment="Top" Width="522"/>
<Label Content="Label" HorizontalAlignment="Left" Margin="15,131,0,0" VerticalAlignment="Top" Width="77" Height="23"/>
<TextBox HorizontalAlignment="Left" Height="23" Margin="97,131,0,0" Text="{Binding EmployeeSalary, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource NullableValueConverter}}" VerticalAlignment="Top" Width="522"/>
<Label Content="Label" HorizontalAlignment="Left" Margin="15,176,0,0" VerticalAlignment="Top" Width="77" Height="23"/>
<TextBox HorizontalAlignment="Left" Height="23" Margin="97,176,0,0" Text="{Binding EmployeeDesigner, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" Width="522"/>
<Label Content="Label" HorizontalAlignment="Left" Margin="15,221,0,0" VerticalAlignment="Top" Width="77" Height="23"/>
<TextBox HorizontalAlignment="Left" Height="23" Margin="97,221,0,0" Text="{Binding SelectedEmployee.EmployeeEmailID, Mode=TwoWay}" VerticalAlignment="Top" Width="522"/>
<Button Content="Button" HorizontalAlignment="Left" Margin="663,116,0,0" VerticalAlignment="Top" Width="75" RenderTransformOrigin="-0.017,0.456" Command="{Binding SaveCommand}"/>
</Grid>
</Window>
RelayCommand.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace OneWayTwoWayBinding
{
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion // Fields
#region Constructors
public RelayCommand(Action<object> execute) : this(execute, null) { }
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute; _canExecute = canExecute;
}
#endregion // Constructors
#region ICommand Members
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter) { _execute(parameter); }
#endregion // ICommand Members
}
}
Hmm, maybe this solution will be okay for you?
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using System.Collections.Generic;
using System.Linq;
namespace WpfApp1
{
public class EmployeeModel
{
public string Name { get; set; }
}
public class EmployeeViewModel : ViewModelBase
{
readonly EmployeeModel model;
string editName;
public EmployeeViewModel (EmployeeModel model)
{
this.model = model;
editName = Name;
SaveChanges = new RelayCommand (() => { Name = EditName; SaveChanges.RaiseCanExecuteChanged (); }, () => IsDirty);
}
public string Name
{
get => model.Name;
set
{
model.Name = value;
RaisePropertyChanged (nameof (Name));
}
}
public string EditName
{
get => editName;
set
{
editName = value;
RaisePropertyChanged (nameof (EditName));
SaveChanges.RaiseCanExecuteChanged ();
}
}
public bool IsDirty => editName != Name;
public RelayCommand SaveChanges { get; }
}
public class WindowViewModel
{
List<EmployeeModel> models = new List<EmployeeModel>
{
new EmployeeModel () { Name = "Janusz" },
new EmployeeModel () { Name = "Grażyna" },
new EmployeeModel () { Name = "John" },
};
public WindowViewModel ()
{
EmployeeViews = models.Select (x => new EmployeeViewModel (x)).ToList ();
}
public IEnumerable<EmployeeViewModel> EmployeeViews { get; }
public EmployeeViewModel SelectedEmployeeView { get; set; }
}
}
And xaml:
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<local:WindowViewModel/>
</Window.DataContext>
<Grid>
<ListBox ItemsSource="{Binding EmployeeViews}"
SelectedItem="{Binding SelectedEmployeeView}"
DisplayMemberPath="Name" Margin="26,26,565.6,0"
Height="274"
VerticalAlignment="Top"
Width="202"
/>
<Button Command="{Binding SelectedEmployeeView.SaveChanges}"
Content="Save"
HorizontalAlignment="Left"
Height="36"
Margin="245,81,0,0"
VerticalAlignment="Top"
Width="133"/>
<TextBox Text="{Binding SelectedEmployeeView.EditName, UpdateSourceTrigger=PropertyChanged}"
HorizontalAlignment="Left"
Height="23"
Margin="255,35,0,0"
TextWrapping="Wrap"
VerticalAlignment="Top"
Width="120"/>
</Grid>
</Window>
I have solved my problem on my own. I have placed my entire code below :)
Employee.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Windows;
using System.Collections.ObjectModel;
using System.Windows.Data;
using System.Windows.Threading;
namespace OneWayTwoWayBinding
{
public class Employee : INotifyPropertyChanged
{
private string employeeName;
private string employeeID;
private int? employeeSalary;
private string employeeDesigner;
private string employeeEmailID;
private Employee selectedEmployee;
private ICollectionView filteredCollection;
private string dynamicSearch;
private int changedPathBinding;
public string EmployeeName
{
get
{
return employeeName;
}
set
{
employeeName = value;
if (FilteredCollection != null)
FilteredCollection.Filter = x => (String.IsNullOrEmpty(employeeName) || ((Employee)x).EmployeeName.Contains(employeeName));
OnPropertyChanged("EmployeeName");
}
}
public string EmployeeID
{
get
{
return employeeID;
}
set
{
employeeID = value;
OnPropertyChanged("EmployeeID");
}
}
public int? EmployeeSalary
{
get
{
return employeeSalary;
}
set
{
employeeSalary = value;
OnPropertyChanged("EmployeeSalary");
if (FilteredCollection != null)
FilteredCollection.Filter = x => ((employeeSalary == null) || ((Employee)x).EmployeeSalary == employeeSalary);
}
}
public string EmployeeDesigner
{
get
{
//Application.Current.Dispatcher.BeginInvoke(new Action(() => MessageBox.Show(employeeDesigner)));
return employeeDesigner;
}
set
{
employeeDesigner = value;
OnPropertyChanged("EmployeeDesigner");
if (FilteredCollection != null)
FilteredCollection.Filter = x => (String.IsNullOrEmpty(employeeDesigner) || ((Employee)x).EmployeeDesigner.Contains(employeeDesigner));
}
}
public string EmployeeEmailID
{
get
{
return employeeEmailID;
}
set
{
employeeEmailID = value;
OnPropertyChanged("EmployeeEmailID");
}
}
public IList<Employee> EmployeeList
{
get; set;
}
public Employee SelectedEmployee
{
get
{
//Application.Current.Dispatcher.BeginInvoke(new Action(() => MessageBox.Show(selectedEmployee.SelectedEmployee.ToString())));
return selectedEmployee;
}
set
{
selectedEmployee = value;
OnPropertyChanged("SelectedEmployee");
}
}
public string DynamicSearch
{
get
{
if (SelectedEmployee == null)
{
EmployeeName = dynamicSearch;
}
return dynamicSearch;
}
set
{
dynamicSearch = value;
OnPropertyChanged("DynamicSearch");
}
}
public ICollectionView FilteredCollection
{
get
{
return filteredCollection;
}
set
{
filteredCollection = value;
OnPropertyChanged("FilteredCollection");
}
}
public int ChangedPathBinding
{
get
{
//Application.Current.Dispatcher.BeginInvoke(new Action(() => MessageBox.Show(changedPathBinding.ToString())));
return changedPathBinding;
}
set
{
changedPathBinding = value;
OnPropertyChanged("ChangedPathBinding");
//SelectedEmployee.EmployeeName
}
}
public ObservableCollection<Employee> Employees { get; private set; }
public event PropertyChangedEventHandler PropertyChanged = null;
virtual protected void OnPropertyChanged(string propName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}
EmployeeViewModel.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
namespace OneWayTwoWayBinding
{
public class EmployeeViewModel : Employee
{
public EmployeeViewModel()
{
ObservableCollection<Employee> Employees = new ObservableCollection<Employee>()
{
new Employee{EmployeeName = "Adrian",EmployeeID = "1",EmployeeSalary = 15000,EmployeeDesigner = "SoftwareEngingeer12312", EmployeeEmailID = "drozd001#gmail423423.com"},
new Employee{EmployeeName = "Bartek",EmployeeID = "2",EmployeeSalary = 15000,EmployeeDesigner = "SoftwareEngingeer",EmployeeEmailID = "drozd001#gmail.com"},
new Employee{EmployeeName = "Czarek",EmployeeID = "3",EmployeeSalary = 30000,EmployeeDesigner = "SoftwareEngingeer",EmployeeEmailID = "drozd001#gmail.com"}
};
FilteredCollection = CollectionViewSource.GetDefaultView(Employees);
//SelectedEmployee = new Employee {EmployeeName = string.Empty, EmployeeID = string.Empty, EmployeeSalary = string.Empty, EmployeeDesigner = string.Empty, EmployeeEmailID = string.Empty};
//EmployeeDesigner = "SoftwareEngingeer12312";
//EmployeeDesigner = "SoftwareEngingeer12312";
//DynamicSearch.EmployeeName = "Czarek";
//EmployeeSalary = 10;
ChangedPathBinding = -1;
SelectedEmployee = null;
}
RelayCommand _saveCommand;
public ICommand SaveCommand
{
get
{
if (_saveCommand == null)
{
_saveCommand = new RelayCommand((param) => this.Save(param),
param => this.CanSave);
}
return _saveCommand;
}
}
public void Save(object parameter)
{
string[] SearchedCollection = ((string)parameter).Split(new char[] { ':' });
SelectedEmployee.EmployeeName = SearchedCollection[0];
//FilteredCollection.Filter = null;
SelectedEmployee = null;
//EmployeeName = null;
//EmployeeSalary = null;
}
bool CanSave
{
get
{
return SelectedEmployee != null;
}
}
}
}
Converters.cs
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;
namespace OneWayTwoWayBinding
{
public class Converters : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
//value = 5; //ta liczba pojawi sie w textbox po uruchomieniu aplikacji
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (string.IsNullOrEmpty(value.ToString()))
return null;
//int var;
//var = int.Parse(value.ToString());
//var *= 2;
//value = var;
return value; //liczba wpisana w textbox z poziomu widoku aplikacji
}
}
public class ConverterFiltering : IMultiValueConverter
{
public object Convert(object[] value, Type targetType, object parameter, CultureInfo culture)
{
if (value[0] == DependencyProperty.UnsetValue || value[1] == DependencyProperty.UnsetValue)
{
return value[0];
}
return value[0];
}
public object[] ConvertBack(object value, Type[] targetType, object parameter, CultureInfo culture)
{
string[] values = new string[2];
values[0] = value.ToString();
values[1] = value.ToString();
return values;
}
}
public class ConverterButton : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string _employeeName = (string)values[0];
//MessageBox.Show("ButtonConverter: " + _employeeName);
return string.Format("{0}", _employeeName);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
MainWindows.xaml.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace OneWayTwoWayBinding
{
/// <summary>
/// Logika interakcji dla klasy MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new EmployeeViewModel();
}
}
}
MainWindow.xaml
<Window x:Class="OneWayTwoWayBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:OneWayTwoWayBinding"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<local:Converters x:Key="NullableValueConverter" />
<local:ConverterFiltering x:Key="ConverterFiltering" />
<local:ConverterButton x:Key="ConverterButton" />
</Window.Resources>
<Grid Margin="0,0,0,20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListView Name="EmployeeListView" HorizontalAlignment="Left" Height="160" Margin="0,259,0,0" VerticalAlignment="Top" Width="792" ItemsSource="{Binding FilteredCollection}" SelectedItem="{Binding SelectedEmployee, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedIndex="{Binding ChangedPathBinding}" >
<ListView.View>
<GridView>
<GridViewColumn Header="EmployeeName" Width="150" DisplayMemberBinding="{Binding EmployeeName}" />
<GridViewColumn Header="EmployeeID" Width="150" DisplayMemberBinding="{Binding EmployeeID}" />
<GridViewColumn Header="EmployeeSalary" Width="150" DisplayMemberBinding="{Binding EmployeeSalary}" />
<GridViewColumn Header="EmployeeDesigner" Width="150" DisplayMemberBinding="{Binding EmployeeDesigner}" />
<GridViewColumn Header="EmployeeEmailID" Width="150" DisplayMemberBinding="{Binding EmployeeEmailID}" />
</GridView>
</ListView.View>
</ListView>
<Label Content="Employee Name" HorizontalAlignment="Left" Margin="15,52,0,0" VerticalAlignment="Top" Width="77" Height="23"/>
<TextBox Name ="TextboxEmployeeName" HorizontalAlignment="Left" Height="23" Margin="97,52,0,0" VerticalAlignment="Top" Width="522" >
<TextBox.Text>
<MultiBinding Converter="{StaticResource ConverterFiltering}" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
<Binding Path="SelectedEmployee.EmployeeName" Mode="OneWay" UpdateSourceTrigger="PropertyChanged" />
<Binding Path="DynamicSearch" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"/>
</MultiBinding>
</TextBox.Text>
</TextBox>
<Label Content="Label" HorizontalAlignment="Left" Margin="15,91,0,0" VerticalAlignment="Top" Width="77" Height="23"/>
<TextBox HorizontalAlignment="Left" Height="23" Margin="97,91,0,0" Text="{Binding Path=SelectedEmployee.EmployeeID, Mode=TwoWay}" VerticalAlignment="Top" Width="522"/>
<Label Content="Label" HorizontalAlignment="Left" Margin="15,131,0,0" VerticalAlignment="Top" Width="77" Height="23"/>
<TextBox HorizontalAlignment="Left" Height="23" Margin="97,131,0,0" Text="{Binding EmployeeSalary, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource NullableValueConverter}}" VerticalAlignment="Top" Width="522"/>
<Label Content="Label" HorizontalAlignment="Left" Margin="15,176,0,0" VerticalAlignment="Top" Width="77" Height="23"/>
<TextBox HorizontalAlignment="Left" Height="23" Margin="97,176,0,0" Text="{Binding EmployeeDesigner, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" Width="522"/>
<Label Content="Label" HorizontalAlignment="Left" Margin="15,221,0,0" VerticalAlignment="Top" Width="77" Height="23"/>
<TextBox HorizontalAlignment="Left" Height="23" Margin="97,221,0,0" Text="{Binding SelectedEmployee.EmployeeEmailID, Mode=TwoWay}" VerticalAlignment="Top" Width="522"/>
<Button Content="Button" HorizontalAlignment="Left" Margin="663,116,0,0" VerticalAlignment="Top" Width="75" RenderTransformOrigin="-0.017,0.456" Command="{Binding SaveCommand}" >
<Button.CommandParameter>
<MultiBinding Converter="{StaticResource ConverterButton}" UpdateSourceTrigger="Explicit" Mode="TwoWay">
<Binding ElementName="TextboxEmployeeName" Path="Text"/>
</MultiBinding>
</Button.CommandParameter>
</Button>
</Grid>
</Window>
RelayCommand.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace OneWayTwoWayBinding
{
public class RelayCommand : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion // Fields
#region Constructors
public RelayCommand(Action<object> execute) : this(execute, null) { }
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute; _canExecute = canExecute;
}
#endregion // Constructors
#region ICommand Members
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void Execute(object parameter) { _execute(parameter); }
#endregion // ICommand Members
}
}

Am I following the MVVM pattern correctly? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
Did I break the rules of MVVM if ever have that rule?
Did I connect my database correctly?
My XML
<Window x:Class="WpfApplication7.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewBox="clr-namespace:WpfApplication7.ViewModel"
xmlns:vm="clr-namespace:WpfApplication7.ViewModel.Command"
xmlns:local="clr-namespace:WpfApplication7"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<viewBox:viewModel x:Key="testView"/>
</Window.Resources>
<Grid DataContext="{Binding Source={StaticResource testView}}">
<TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Margin="175,47,0,0" Text="{Binding fname, Source={StaticResource testView}}"/>
<Button x:Name="button" Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="0,95,0,0" Command="{Binding test, Source={StaticResource testView}}"/>
<TextBox x:Name="textBox_Copy" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Margin="175,81,0,0" Text="{Binding mname, Source={StaticResource testView}}"/>
<TextBox x:Name="textBox_Copy1" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Margin="175,109,0,0" Text="{Binding lname, Source={StaticResource testView}}"/>
<TextBox x:Name="textBox_Copy2" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Margin="175,175,0,0" Text="{Binding IDNum}"/>
</Grid>
</Window>
This is my ViewModel Class
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WpfApplication7.ViewModel.Command;
using WpfApplication7.Model;
namespace WpfApplication7.ViewModel
{
public class viewModel : INotifyPropertyChanged
{
private databaseTest obj = new databaseTest();
public btnTest test { get; set; }
public viewModel()
{
test = new btnTest(this);
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string property)
{
if(PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
public string fname
{
get { return obj.firstname; }
set { obj.firstname = value;
OnPropertyChanged("fname");
}
}
public string mname
{
get { return obj.middlename; }
set { obj.middlename = value;
OnPropertyChanged("mname");
}
}
public string lname
{
get { return obj.lastname; }
set { obj.lastname = value;
OnPropertyChanged("lname");
}
}
public int IDNum
{
get { return obj.idNum; }
set { obj.idNum = value;
OnPropertyChanged("IDNum");
}
}
public void searchBtn()
{
obj.sql = #"Provider = Microsoft.ACE.OLEDB.12.0; data source = C:\Users\veekat\Documents\VeeKat.mdb";
obj.conn = new System.Data.OleDb.OleDbConnection(obj.sql);
obj.cmd = new System.Data.OleDb.OleDbCommand("select * from info where ID = "+ this.IDNum +"", obj.conn);
try
{
obj.conn.Open();
obj.dr = obj.cmd.ExecuteReader();
if (obj.dr.Read())
{
this.fname = obj.dr["Firstname"].ToString();
this.mname = obj.dr["Middlename"].ToString();
this.lname = obj.dr["Lastname"].ToString();
}
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
This is my Command class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace WpfApplication7.ViewModel.Command
{
public class btnTest : ICommand
{
public viewModel viewM { get; set; }
public btnTest(viewModel vw)
{
this.viewM = vw;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
viewM.searchBtn();
}
}
}
And here my Model Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Data.OleDb;
namespace WpfApplication7.Model
{
public class databaseTest
{
private string Firstname;
private string Middlename;
private string Lastname;
public string firstname
{
get { return Firstname; }
set { Firstname = value; }
}
public string middlename
{
get { return Middlename; }
set { Middlename = value; }
}
public string lastname
{
get { return Lastname; }
set { Lastname = value; }
}
private int num;
public int idNum
{
get { return num; }
set { num = value; }
}
public string sql { get; set; }
public OleDbConnection conn { get; set; }
public OleDbCommand cmd { get; set; }
public OleDbDataReader dr { get; set; }
}
}
So far I don't have any errors, but I want to know your opinion.
as you can see, i search it using the id number
The MVVM pattern you followed is not incorrect. But it could be improved.
In my opinion the best thing to do is to separate the database related stuff to a new class file.
Add a new class file DBManager and add all the database related CRUD operations inside the class file. Make this class a singleton class. It's upto you. The use of separating the db operations is that when your project becomes very large, it is easy to manipulate data when it is in a single file, rather than dealing it in every model.
Is your question "is it good practise to place my database IO inside my MVVM ViewModel ?" In which case a good discussion of this can be found in this MVVM where to put Data Access Layer? "MVVM where to put Data Access Layer?" which should point you in the right direction.

Binding data to ListBox in xaml getting data from webservice

I have this code:
using System;
using System.Collections.Generic;
using System.linq;
using System.Text;
using System.Threading.Tasks;
using System.Component-model;
namespace MEO.MODELS
{
public class Claims :INotifyPropertyChanged
{
public Claims()
{
}
private string description;
private string expenseHeaderId;
private string assginedTo;
private bool submitted;
private bool approved;
private bool authorised;
private DateTime updatedDate;
private DateTime createdDate;
private DateTime claimDate;
private DateTime lastModifiedDate;
private string expenseFormType;
public bool Approved
{
get
{
return this.approved;
}
set
{
if (value != this.approved)
{
this.approved = value;
this.NotfiyProperty("Approved");
}
}
}
public string AssignedTo
{
get
{
return this.assginedTo;
}
set
{
if (value != this.assginedTo)
{
this.assginedTo = value;
this.NotfiyProperty("AssignedTo");
}
}
}
public bool Authorised
{
get
{
return this.authorised;
}
set
{
if (value != authorised)
{
this.authorised = value;
this.NotfiyProperty("Authorised");
}
}
}
public bool Submitted
{
get
{
return this.submitted;
}
set
{
if (value != submitted)
{
this.submitted = value;
this.NotfiyProperty("Submitted");
}
}
}
public DateTime ClaimDate
{
get
{
return this.claimDate;
}
set
{
if (value != claimDate)
{
this.claimDate = value;
this.NotfiyProperty("ClaimDate");
}
}
}
public DateTime CreatedDate
{
get
{
return this.createdDate;
}
set
{
if (value != createdDate)
{
this.createdDate = value;
this.NotfiyProperty("CreatedDate");
}
}
}
public DateTime LastModifiedDate
{
get
{
return this.lastModifiedDate;
}
set
{
if (value != lastModifiedDate)
{
this.lastModifiedDate = value;
this.NotfiyProperty("LastModifiedDate");
}
}
}
public DateTime UpdatedDate
{
get
{
return this.updatedDate;
}
set
{
if (value != updatedDate)
{
this.updatedDate = value;
this.NotfiyProperty("UpdatedDate");
}
}
}
public string Description
{
get
{
return this.description;
}
set
{
if (value != this.description)
{
this.description = value;
this.NotfiyProperty("Description");
}
}
}
public string ExpenseFormType
{
get
{
return this.expenseFormType;
}
set
{
if (value != this.expenseFormType)
{
this.expenseFormType = value;
this.NotfiyProperty("ExpenseFormType");
}
}
}
public string ExpenseHeaderId
{
get
{
return this.expenseHeaderId;
}
set
{
if (value != this.expenseHeaderId)
{
this.expenseHeaderId = value;
this.NotfiyProperty("ExpenseHeaderId");
}
}
}
private void NotfiyProperty(string propertyName)
{
PropertyChangedEventHandler propertyChangedEventHandler = this.PropertyChanged;
if (propertyChangedEventHandler != null)
{
propertyChangedEventHandler.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
And the following is the XAML which contains a Listbox.I have to bind the data getting from webservice calling a method called GetFullClaimLinesAsync by passing parameters when page is loaded.
<phone:PhoneApplicationPage
x:Class="MEO.Views.Result"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
mc:Ignorable="d"
shell:SystemTray.IsVisible="True">
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Margin="12,17,0,28" Grid.ColumnSpan="2">
<Button Content="My Expenses On line" Background="#00ccff" Grid.Row="5" FontWeight="Bold" Name="head" Margin="-23,0,-13,-98" Foreground="White" BorderThickness="0"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Margin="0,35,24,10" Grid.ColumnSpan="2"/>
<!--<Button Content="Get Full Claims" Background="#00ccff" FontWeight="Bold" x:Name="claim" Click="claim_Click" Margin="67,105,97,-203" Foreground="White" BorderThickness="0" Grid.Row="1" RenderTransformOrigin="0.676,0.469"/>-->
<Grid Margin="0,203,10,-713" Grid.Row="1" >
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="0*"/>
</Grid.ColumnDefinitions>
<ListBox HorizontalAlignment="Left" Name="listbox1" ItemsSource="{Binding}" VerticalAlignment="Top" Height="500" Width="0">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<Grid Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50">
</ColumnDefinition>
<ColumnDefinition Width="50">
</ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Description}" Margin="=3" Grid.Column="0"></TextBlock>
<TextBlock Text="{Binding ExpenseHeaderId}" Margin="=3" Grid.Column="1"></TextBlock>
</Grid>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Grid>
</phone:PhoneApplicationPage>
and the following is the code behind file (Result.xaml.cs):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using System.Xml.Linq;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using System.IO;
using System.Net.NetworkInformation;
using System.Text;
using System.ComponentModel;
using System.Collections.ObjectModel;
using MEO.MODELS;
namespace MEO.Views
{
public partial class Result : PhoneApplicationPage
{
//public Guid rid = new Guid(NavigationContext.QueryString["id"]);
//public string rpswd = NavigationContext.QueryString["password"];
//public DateTime headerFromDate = DateTime.Today;
//public DateTime detaiFromDate = DateTime.Today;
ObservableCollection<Claims> oc = new ObservableCollection<Claims>();
public Result()
{
InitializeComponent();
Guid rid = new Guid("0525466131154515");
string rpswd = "hchdj455mjchdjkch7dc1njj";
DateTime headerFromDate = Convert.ToDateTime("555525545");
DateTime detaiFromDate = Convert.ToDateTime("38635");
LoginService.DXDataMobileSoapClient client = new LoginService.DXDataMobileSoapClient();
client.GetFullClaimLinesCompleted+=client_GetFullClaimLinesCompleted;
client.GetFullClaimLinesAsync(rid, rpswd, "", headerFromDate, detaiFromDate, rid);
}
private void client_GetFullClaimLinesCompleted(object sender, LoginService.GetFullClaimLinesCompletedEventArgs e)
{
try
{
if (e.Error == null)
{
XElement[] array = Enumerable.ToArray<XElement>(e.Result.ReturnedDataTable.Any1.Descendants("ClaimHeadersDT"));
if (Enumerable.Count<XElement>(array) > 0)
{
//ObservableCollection<Claims> oc = new ObservableCollection<Claims>();
for (int i = 0; i < Enumerable.Count<XElement>(array); i++)
{
oc.Add(new Claims()
{
Description = (string)array[i].Element("h_description"),
ExpenseHeaderId =(string)array[i].Element("h_expense_headerID"),
});
}
listbox1.ItemsSource = oc;
}
}
}
catch(Exception ex)
{
throw ex;
}
}
}
}
My problem is that I am getting data from web service i.e. from XML and the data is added to my collection i.e. ObservableCollection oc. But I am unable to bind the oc data to list box. I am getting error in App.xaml like unhandeled exception. The error is not catched in my catch block. However Listbox.Itemssource has data, containing 603 items.
i think you get this problem because the listbox use a Model as Datatemplate, what you getting from the webserver is xml data and turning to a string, i did something like that before, and goas like that...
private void client_GetFullClaimLinesCompleted(class.......)
{
oc.ItemsSource = e.Result;
}
as you said, you're getting 603 results but they can't be recognized on DataTemplate Model

How to trigger a new validation when a textbox gets enabled?

In a wpf dialog window I have a checkbox that enables and disables a textbox. The textbox has ValidatesOnDataErrors set to True. Via IDataErrorInfo I check the value of this textbox only, if the checkbox is checked.
My problem is that if the user checks the checkbox there is no new validation on textbox performed and therefor I dont get this red frame indicating an error.
For demonstration here is a small sample:
<Window x:Class="Validation.ValidationWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ValidationWindow" Height="300" Width="300">
<DockPanel LastChildFill="False">
<CheckBox DockPanel.Dock="Top" IsChecked="{Binding InputAllowed}">Input allowed</CheckBox>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<Label>InputValue</Label>
<TextBox Text="{Binding InputValue, ValidatesOnDataErrors=True}" IsEnabled="{Binding InputAllowed}" Width="50"/>
</StackPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<Label>InputValue2</Label>
<TextBox Text="{Binding InputValue2, ValidatesOnDataErrors=True}" Width="50"/>
</StackPanel>
<Button DockPanel.Dock="Bottom" Click="OnOk">Ok</Button>
</DockPanel>
</Window>
code behind:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace Validation
{
/// <summary>
/// Interaction logic for ValidationWindow.xaml
/// </summary>
public partial class ValidationWindow : Window, IDataErrorInfo
{
public bool InputAllowed
{
get { return (bool)GetValue(InputAllowedProperty); }
set { SetValue(InputAllowedProperty, value); }
}
public static readonly DependencyProperty InputAllowedProperty =
DependencyProperty.Register("InputAllowed", typeof(bool), typeof(ValidationWindow), new PropertyMetadata(false));
public int InputValue
{
get { return (int)GetValue(InputValueProperty); }
set { SetValue(InputValueProperty, value); }
}
public static readonly DependencyProperty InputValueProperty =
DependencyProperty.Register("InputValue", typeof(int), typeof(ValidationWindow), new PropertyMetadata(0));
public int InputValue2
{
get { return (int)GetValue(InputValue2Property); }
set { SetValue(InputValue2Property, value); }
}
public static readonly DependencyProperty InputValue2Property =
DependencyProperty.Register("InputValue2", typeof(int), typeof(ValidationWindow), new PropertyMetadata(0));
public ValidationWindow()
{
InitializeComponent();
DataContext = this;
}
private void OnOk(object sender, RoutedEventArgs e)
{
string msg = Error;
if(!string.IsNullOrEmpty(Error))
{
MessageBox.Show(Error);
return;
}
DialogResult = true;
}
#region IDataErrorInfo Members
public string Error
{
get { return ((IDataErrorInfo)this)[null]; }
}
public string this[string columnName]
{
get
{
string msg = string.Empty;
if(string.IsNullOrEmpty(columnName))
{
msg += ((IDataErrorInfo)this)["InputValue"];
msg += ((IDataErrorInfo)this)["InputValue2"];
}
else
{
switch(columnName)
{
case "InputValue":
if(InputAllowed)
{
if(InputValue <= 0)
{
msg += "InputValue must be greater that 0!";
}
}
break;
case "InputValue2":
if(InputValue2 <= 0)
{
msg += "InputValue2 must be greater that 0!";
}
break;
}
}
return msg;
}
}
#endregion
}
}
We've been using this to force validation after programatcially changing text, should work as well if you call it in reponse to your checkbox's events:
var binding = someTextBox.GetBindingExpression( TextBox.TextProperty );
if( binding == null )
return;
binding.UpdateSource();
No actual difference from stijn's solution but since we're all a little lazy:
public static class DependencyPropertyExtensions
{
public static bool UpdateSource(this FrameworkElement source, DependencyProperty property)
{
var binding = source.GetBindingExpression(property);
if (binding != null)
{
binding.UpdateSource();
return true;
}
return false;
}
}

Categories

Resources