I'm curently trying to implemnt a Combobox binding to a list and some labels showing the details of a selected object. The binding to the Combobox works without any problems but I don't want to add extra variables into my ViewModel just to display the name and speed of my car objects.
Is there any way to Map the object variables of the selected combobox item on to the labels without adding additional variables into my ViewModel?
That's the code I'm currently working with
MainWondow.xaml.cs
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 StackOF
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private ViewModel viewModel;
public MainWindow()
{
viewModel = new ViewModel();
DataContext = viewModel;
InitializeComponent();
}
}
}
ViewModel.cs
using _02_WPFCarInfo.AutoKlassen;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace StackOF
{
public class ViewModel : INotifyPropertyChanged
{
private ObservableCollection<AutoModel> _autoModels;
private AutoModel selectedModel;
public ObservableCollection<AutoModel> AutoModels
{
get { return _autoModels; }
set
{
_autoModels = value;
OnPropertyChanged();
}
}
public AutoModel SelectedModel
{
get { return selectedModel; }
set
{
selectedModel = value;
OnPropertyChanged();
}
}
public ViewModel()
{
_autoModels = generateCars();
}
private ObservableCollection<AutoModel> generateCars()
{
AutoModel model1 = new AutoModel();
AutoModel model2 = new AutoModel();
AutoModel model3 = new AutoModel();
model1.name = "Mercedes C12 Pro";
model1.speed = "125 km\\h";
model2.name = "Audi A12";
model2.speed = "236 km\\h";
model3.name = "Audi S20 Pro";
model3.speed = "300 km\\h";
ObservableCollection<AutoModel> cars = new ObservableCollection<AutoModel>();
cars.Add(model1);
cars.Add(model2);
cars.Add(model3);
return cars;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
MainWindow.xaml
<Window x:Class="StackOF.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:StackOF"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<ComboBox SelectedItem="{Binding SelectedModel}" DisplayMemberPath="name" ItemsSource="{Binding AutoModels}" HorizontalAlignment="Center" Margin="0,164,0,0" VerticalAlignment="Top" Width="212"/>
<Label Content="Name:" HorizontalAlignment="Left" Margin="294,231,0,0" VerticalAlignment="Top"/>
<Label Content="Speed:" HorizontalAlignment="Left" Margin="294,262,0,0" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Center" Margin="0,241,0,0" TextWrapping="Wrap" Text="---" VerticalAlignment="Top" RenderTransformOrigin="0.287,-1.303"/>
<TextBlock HorizontalAlignment="Center" Margin="0,267,0,0" TextWrapping="Wrap" Text="---" VerticalAlignment="Top" RenderTransformOrigin="0.287,-1.303"/>
</Grid>
</Window>
AutoModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _02_WPFCarInfo.AutoKlassen
{
public class AutoModel
{
public String name { get; set; }
public String speed { get; set; }
public AutoModel()
{
this.speed = String.Empty;
this.name = String.Empty;
}
public AutoModel(String name, String speed)
{
this.speed = speed;
this.name = name;
}
}
}
I thought about something like :
<TextBlock HorizontalAlignment="Center" Margin="0,241,0,0" TextWrapping="Wrap" Text="{Binding SelectedModel.name}" VerticalAlignment="Top" RenderTransformOrigin="0.287,-1.303"/>
<TextBlock HorizontalAlignment="Center" Margin="0,267,0,0" TextWrapping="Wrap" Text="{Binding SelectedModel.speed}" VerticalAlignment="Top" RenderTransformOrigin="0.287,-1.303"/>
But obviously it is not possible to select the variables of "SelectedModel" that way.
Ok nvm it DOES work. It only does not work if you have a textblock with opening and closing tag with text inbetween
This works:
<TextBlock HorizontalAlignment="Center" Margin="0,241,0,0" TextWrapping="Wrap" Text="{Binding SelectedModel.name}" VerticalAlignment="Top" RenderTransformOrigin="0.287,-1.303"/>
but this doesn't
<TextBlock HorizontalAlignment="Center" Margin="0,241,0,0" TextWrapping="Wrap" Text="{Binding SelectedModel.name}" VerticalAlignment="Top" RenderTransformOrigin="0.287,-1.303">---</TextBlock>
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
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
}
}
I want to implement feature in my WPF application like if someone has log in and he is filling a registration form,but after sometime the account is automatically logout(already implemented this feature),then when the user sign in again, then how to display him the application in the same old state i.e the half filled form or anything he was doing previously with his account,i am looking on net but unable to find any help on this.
There is no quick easy way to do this... However, I would do it like this.
Use the MVVM pattern. As the user enters info into the View, your ViewModel will get the data. When the user logs out, your application should serialize your ViewModel to your favorite format. Mine is JSON. Using JSON.NET, you can serialize the viewmodel out to file.
On startup, you would deserialize the file and restore your viewmodel. Voila, your view should be right back to where it was when they closed the app.
I have made it-
MainWindow.xaml
<Window x:Class="SerializeDeSerialize.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Nikita="clr-namespace:SerializeDeSerialize"
Title="MainWindow" Height="350" Width="525" Closed="Window_Closed_1" Loaded="Window_Loaded_1">
<Window.DataContext>
<Nikita:Movie></Nikita:Movie>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Name="lblTitle" Content="Title:" Grid.Row="0" Grid.Column="0" Margin="10,25,63,10" HorizontalAlignment="Left" Width="164"></Label>
<TextBox Grid.Row="0" Name="txtTitle" Grid.Column="1" Margin="10,25,63,10" Text="{Binding Title}"></TextBox>
<Label Grid.Row="1" Name="lblRating" Content="Rating:" Grid.Column="0" Margin="10,25,63,10" HorizontalAlignment="Left" Width="164"></Label>
<TextBox Grid.Row="1" Name="txtRating" Grid.Column="1" Margin="10,25,63,10" Text="{Binding Rating}"></TextBox>
<Label Grid.Row="2" Name="lblReleaseDate" Content="Release Date:" Grid.Column="0" Margin="10,25,63,10" HorizontalAlignment="Left" Width="164"></Label>
<TextBox Grid.Row="2" Name="txtReleaseDate" Grid.Column="1" Margin="10,25,63,10" Text="{Binding ReleaseDate}"></TextBox>
<Button Grid.Row="3" Content="Window1" Margin="66,36,69,10" Click="Button_Click_1"></Button>
<Button Grid.Row="4" Content="Window2" Margin="66,36,69,10" Click="Button_Click_2"></Button>
</Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.IO;
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;
using System.Xml.Serialization;
namespace SerializeDeSerialize
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
SerializeDeSerialize.Movie mv = new Movie();
static Movie mm = new Movie();
public MainWindow()
{
InitializeComponent();
DataContext = mv;
}
private void Window_Closed_1(object sender, EventArgs e)
{
SerializeToXML(mv);
}
static public void SerializeToXML(Movie movie)
{
XmlSerializer serializer = new XmlSerializer(typeof(Movie));
TextWriter textWriter = new StreamWriter(#"C:\Users\398780\Desktop\Nikita\movie.xml");
serializer.Serialize(textWriter, movie);
textWriter.Close();
}
private void Window_Loaded_1(object sender, RoutedEventArgs e)
{
mm=DeserializeFromXML();
txtTitle.Text = mm.Title;
txtRating.Text =Convert.ToString(mm.Rating);
txtReleaseDate.Text = Convert.ToString(mm.ReleaseDate);
}
static Movie DeserializeFromXML()
{
XmlSerializer deserializer = new XmlSerializer(typeof(Movie));
TextReader textReader = new StreamReader(#"C:\Users\398780\Desktop\Nikita\movie.xml");
mm=(Movie)deserializer.Deserialize(textReader);
textReader.Close();
return mm;
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
Window1 win1 = new Window1();
win1.Show();
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
Window2 win2 = new Window2();
win2.Show();
}
}
}
MVVM-movie.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SerializeDeSerialize
{
public class Movie
{
private string _title;
private int _rating;
private DateTime _releaseDate;
public Movie()
{
}
public string Title
{
get { return _title; }
set { _title = value; }
}
public int Rating
{
get { return _rating; }
set { _rating = value; }
}
public DateTime ReleaseDate
{
get { return _releaseDate; }
set { _releaseDate = value; }
}
}
}
Please check..it is same as you told or not?