As the title says, im trying to display the hardcoded values I typed in my XAML file through databindings but in 1 method call instead of binding the textboxes in every specific property.
Model:
public class Person
{
public string Namn { get; set; }
public DateTime Födelsedatum { get; set; }
public int Betyg { get; set; }
public int AntalBarn { get; set; }
public int Favoritsiffra { get; set; }
public string Kommentar { get; set; }
}
View:
<Window x:Class="PiedPiper.View.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Inlämningsuppgift WPF" Height="400" Width="400">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Content="Personuppgifter" FontSize="35" Grid.Column="0" Grid.Row="0"></Label>
<Separator Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2" Margin="10,2,-50,2"/>
<Label Content="Namn:" Grid.Column="0" Grid.Row="2" Margin="5,5,210,0"></Label>
<TextBox Name="NamnTextBox" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Margin="118,5,-50,0"/>
<Label Content="Födelsedatum:" Grid.Column="0" Grid.Row="3" Margin="5,5,210,0"></Label>
<TextBox Name="FödelsedatumTextBox" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Margin="118,5,-50,0"></TextBox>
<Label Content="Betyg" Grid.Column="0" Grid.Row="4" Margin="5,5,210,0"></Label>
<ComboBox Name="BetygComboBox" Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2" Margin="218,5,-50,0"></ComboBox>
<Label Content="Antal barn (0-20):" Grid.Column="0" Grid.Row="5" Margin="5,5,210,0"></Label>
<Slider Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="2" Margin="125,5,25,0"></Slider>
<TextBox Name="AntalBarnTextBox" Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="2" Margin="300,5,-50,0"></TextBox>
<Label Content="Favoritsiffra (0-99):" Grid.Column="0" Grid.Row="6" Margin="5,5,210,0"></Label>
<TextBox Name="FavoritsiffraTextBox" Grid.Row="6" Grid.Column="0" Grid.ColumnSpan="2" Margin="225,5,-50,0"></TextBox>
<CheckBox Content="Visa kommentar" Grid.Row="7" Grid.Column="0" Margin="5,5,210,0"></CheckBox>
<TextBox Name="KommentarTextBox" Grid.Row="7" Grid.Column="0" Grid.ColumnSpan="2" Margin="125,5,-50,-50" Grid.RowSpan="2"></TextBox>
<Button Content="Spara" Grid.Row="8" Grid.Column="0" Margin="125,55,-50,-80" Grid.ColumnSpan="2"></Button>
<Separator Grid.Row="9" Grid.Column="0" Grid.ColumnSpan="2" Margin="10,85,-50,-80"></Separator>
<Label Content="Andre Kordasti" Grid.Row="10" Grid.Column="0" Margin="10,85,-50,-80"></Label>
<Button Content="Avsluta" Grid.Row="10" Grid.Column="0" Margin="225,85,-50,-80" Grid.ColumnSpan="2"></Button>
</Grid>
ViewModel:
public class PersonViewModel : INotifyPropertyChanged
{
public PersonViewModel(Person person)
{
Namn = person.Namn;
Födelsedatum = person.Födelsedatum;
Betyg = person.Betyg;
AntalBarn = person.AntalBarn;
Favoritsiffra = person.Favoritsiffra;
Kommentar = person.Kommentar;
GetPerson();
}
private void GetPerson()
{
Namn = "KurtSune";
Födelsedatum = new DateTime(1980, 09, 06);
Betyg = 3;
AntalBarn = 7;
Favoritsiffra = 10;
Kommentar = "Kommentar...";
var mainWindow = new MainWindow();
mainWindow.NamnTextBox.Text = Namn;
mainWindow.FödelsedatumTextBox.Text = Convert.ToString(Födelsedatum);
mainWindow.BetygComboBox.SelectedValue = Betyg;
mainWindow.AntalBarnTextBox.Text = Convert.ToString(AntalBarn);
mainWindow.FavoritsiffraTextBox.Text = Convert.ToString(Favoritsiffra);
mainWindow.KommentarTextBox.Text = Kommentar;
}
public ICommand SaveCommand { get; set; }
public ICommand AbortCommand { get; set; }
public bool CanSave
{
get
{
if (Namn == null)
{
return false;
}
return !String.IsNullOrWhiteSpace(Namn);
}
}
private string _namn;
public string Namn
{
get { return _namn; }
set { _namn = value; OnPropertyChanged("Namn"); }
}
private DateTime _födelsedatum;
public DateTime Födelsedatum
{
get { return _födelsedatum; }
set { _födelsedatum = value; OnPropertyChanged("Födelsedatum"); }
}
private int _betyg;
public int Betyg
{
get { return _betyg; }
set { _betyg = value; OnPropertyChanged("Betyg"); }
}
private int _antalBarn;
public int AntalBarn
{
get { return _antalBarn; }
set { _antalBarn = value; OnPropertyChanged("AntalBarn"); }
}
private int _favoritSiffra;
public int Favoritsiffra
{
get { return _favoritSiffra; }
set { _favoritSiffra = value; OnPropertyChanged("Födelsedatum"); }
}
private string _kommentar;
public string Kommentar
{
get { return _kommentar; }
set { _kommentar = value; OnPropertyChanged("Kommentar"); }
}
private void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
And to add my App.xaml.cs file:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var person = new Person();
var personViewModel = new PersonViewModel(person);
var mainWindow = new MainWindow();
mainWindow.DataContext = personViewModel;
mainWindow.Show();
}
}
So I dont get the following values to be displayed... Please help, Iam new to this.
Here is a simplified example where,
I made a DataTemplate where controls are bound to the Person properties. Benefits are obvious because as you will see whichever end is modified, the other will know/show these changes.
(added a button and a MessageBox to further demonstrate this)
Code:
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
namespace WpfApplication1
{
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
var person = new Person {Name = "name1", Address = "address1"};
person.PropertyChanged += person_PropertyChanged;
DataContext = person;
}
private void person_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
MessageBox.Show("data changed");
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
var dataContext = (Person) DataContext;
dataContext.Name = "newName";
dataContext.Address = "newAddress";
}
}
internal class Person : INotifyPropertyChanged
{
private string _address;
private string _name;
public string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged();
}
}
public string Address
{
get { return _address; }
set
{
_address = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfApplication1="clr-namespace:WpfApplication1"
Title="MainWindow"
Width="525"
Height="350">
<Window.Resources>
<DataTemplate x:Key="PersonTemplate" DataType="wpfApplication1:Person">
<StackPanel>
<TextBlock Text="Name" />
<TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Text="Address" />
<TextBox Text="{Binding Address, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<StackPanel>
<Button Click="ButtonBase_OnClick" Content="Modify" />
<ContentControl Content="{Binding}" ContentTemplate="{StaticResource PersonTemplate}" />
</StackPanel>
</Grid>
</Window>
Now as you can see there are no hard-coded values in XAML, the object I have passed to DataContext has sample values instead.
Related
I have been struggling for weeks with my WPF appliaction named "ContactManager" when i want to add records to the database.
I have two entites:
public partial class Contact : EntityBase
{
public int ContactId { get; set; }
[StringLength(20)]
public string FirstName { get; set; }
[StringLength(20)]
public string LastName { get; set; }
[StringLength(20)]
public string Organization { get; set; }
[StringLength(20)]
public string JobTitle { get; set; }
public string ImagePath { get; set; }
public string CellPhone { get; set; }
public string HomePhone { get; set; }
public string OfficePhone { get; set; }
public string PrimaryEmail { get; set; }
public string SecondaryEmail { get; set; }
public virtual Address Address { get; set; } = new Address();
public class Address : EntityBase
{
[ForeignKey("Contact")]
public int AddressId { get; set; }
public string City { get; set; }
public string Country { get; set; }
public string Line1 { get; set; }
public string Line2 { get; set; }
public string Zip { get; set; }
public string State { get; set; }
public virtual Contact Contact { get; set; }
The add method:
public int Add(Contact entity)
{
Context.Contacts.Add(entity);
var o = SaveChanges();
Context.Dispose();
Context = new CMEntities();
return o;
}
internal int SaveChanges()
{
try
{
return Context.SaveChanges();
}
}
When the database is empty it is working but after closing and restarting the app I get the following exception:
SqlException: Violation of PRIMARY KEY constraint 'PK_dbo.Addresses'. Cannot insert duplicate key in object 'dbo.Addresses'. The duplicate key value is (1).
The statement has been terminated.
I do not understand why Sql server (or entity framework??) wants to insert key 1 instead of the next id...
if i delete rows in table Addresses it is working again, it inserts the row without problem with the next/right addressid.( that is the addressid is not 1 but 5 because of the previous rows of contacts )
In my opinion the schema of( keys etc ) tables are correct the problem is with other issue, maybe binding or context i have not got a clue...
(I made a simpler example omitting MVC, it is working. )
Here is the code of MVC app:
namespace CMnew.Model
{
public partial class ContactRepository : IDisposable
{
public CMEntities Context { get; set; } = new CMEntities();
private List<Contact> _contactStore;
public ContactRepository()
{
if (this.GetAll() == null)
{
_contactStore = new List<Contact>();
}
else
{
_contactStore = this.GetAll();
}
}
public List<Contact> FindByLookup(string lookupName)
{
IEnumerable<Contact> found = from c in _contactStore
where c.LookupName.StartsWith(lookupName, StringComparison.OrdinalIgnoreCase)
select c;
return found.ToList();
}
public List<Contact> FindAll()
{
return new List<Contact>(_contactStore);
}
public void Save(Contact contact)
{
if (_contactStore.Contains(contact))
{
this.SaveToDatabase(contact);
}
else
{
_contactStore.Add(contact);
this.Add(contact);
}
}
public int SaveToDatabase(Contact entity)
{
return SaveChanges();
}
public void Delete(Contact contact)
{
_contactStore.Remove(contact);
DeleteFromDatabase(contact);
}
public int DeleteFromDatabase(Contact entity)
{
Context.Entry(entity).State = EntityState.Deleted;
return SaveChanges();
}
public Contact GetOne(int? id) => Context.Contacts.Find(id);
public List<Contact> GetAll() => Context.Contacts.ToList();
public int Add(Contact entity)
{
Context.Contacts.Add(entity);
var o = SaveChanges();
Context.Dispose();
Context = new CMEntities();
return o;
}
internal int SaveChanges()
{
try
{
return Context.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
throw;
}
catch (DbUpdateException ex)
{
throw;
}
catch (CommitFailedException ex)
{
throw;
}
catch (Exception ex)
{
throw ex;
}
}
bool disposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposed)
{
return;
}
if (disposing)
{
Context.Dispose();
}
disposed = true;
}
}
}
namespace CMnew.Presenters
{
public class ApplicationPresenter : PresenterBase<Shell>, INotifyPropertyChanged
{
private readonly ContactRepository _contactRepository;
private ObservableCollection<Contact> _currentContacts;
public event PropertyChangedEventHandler PropertyChanged;
public ApplicationPresenter(Shell view, ContactRepository contactRepository) : base(view)
{
_contactRepository = contactRepository;
_currentContacts = new ObservableCollection<Contact>(_contactRepository.FindAll());
}
// public ObservableCollection<Contact> CurrentContacts { get; set; }
public ObservableCollection<Contact> CurrentContacts
{
get { return _currentContacts; }
set
{
_currentContacts = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CurrentContacts)));
}
}
public string StatusText { get; set; }
public void Search(string criteria)
{
if (!string.IsNullOrEmpty(criteria) && criteria.Length > 2)
{
CurrentContacts = new ObservableCollection<Contact>(_contactRepository.FindByLookup(criteria));
StatusText = string.Format("{0} contacts found.", CurrentContacts.Count);
}
else
{
CurrentContacts = new ObservableCollection<Contact>(_contactRepository.FindAll());
}
}
public void NewContact()
{
OpenContact(new Contact());
}
public void SaveContact(Contact contact)
{
if (!CurrentContacts.Contains(contact))
{
CurrentContacts.Add(contact);
}
_contactRepository.Save(contact);
StatusText = string.Format("Contact '{0}' was saved.", contact.LookupName);
}
public void DeleteContact(Contact contact)
{
if (CurrentContacts.Contains(contact))
{
CurrentContacts.Remove(contact);
}
_contactRepository.Delete(contact);
StatusText = string.Format("Contact '{0}' was deleted.", contact.LookupName);
}
public void CloseTab<T>(PresenterBase<T> presenter)
{
View.RemoveTab(presenter);
}
private void OpenContact(Contact contact)
{
if (contact == null) return;
View.AddTab(new EditContactPresenter(this, new EditContactView(), contact));
}
public void DisplayAllContacts()
{
throw new NotImplementedException();
}
}
}
namespace CMnew.Presenters
{
public class EditContactPresenter : PresenterBase<EditContactView>
{
private readonly ApplicationPresenter _applicationPresenter;
private Contact _contact;
public EditContactPresenter(ApplicationPresenter applicationPresenter, EditContactView view, Contact contact) : base(view, "Contact.LookupName")
{
_applicationPresenter = applicationPresenter;
_contact = contact;
}
public Contact Contact
{
get { return _contact; }
set { _contact = value; }
}
public void SelectImage()
{
string imagePath = View.AskUserForImagePath();
if (!string.IsNullOrEmpty(imagePath))
{
Contact.ImagePath = imagePath;
}
}
public void Save()
{
_applicationPresenter.SaveContact(Contact);
}
public void Delete()
{
_applicationPresenter.CloseTab(this);
_applicationPresenter.DeleteContact(Contact);
}
public void Close()
{
_applicationPresenter.CloseTab(this);
}
public override bool Equals(object obj)
{
EditContactPresenter presenter = obj as EditContactPresenter;
return presenter != null && presenter.Contact.Equals(Contact);
}
}
}
namespace CMnew.Views
{
/// <summary>
/// Interaction logic for EditContactView.xaml
/// </summary>
public partial class EditContactView : UserControl
{
public EditContactView()
{
InitializeComponent();
}
public EditContactPresenter Presenter
{
get { return DataContext as EditContactPresenter; }
}
private void Save_Click(object sender, RoutedEventArgs e)
{
Presenter.Save();
}
private void Delete_Click(object sender, RoutedEventArgs e)
{
Presenter.Delete();
}
private void Close_Click(object sender, RoutedEventArgs e)
{
Presenter.Close();
}
private void SelectImage_Click(object sender, RoutedEventArgs e)
{
Presenter.SelectImage();
}
public string AskUserForImagePath()
{
OpenFileDialog dlg = new OpenFileDialog();
dlg.ShowDialog();
return dlg.FileName;
}
}
}
<UserControl x:Class="CMnew.Views.EditContactView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CMnew.Views"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<DockPanel Margin="5">
<Border DockPanel.Dock="Top">
<DockPanel LastChildFill="False">
<TextBlock DockPanel.Dock="Left" Text="{Binding Contact.LastName}"/>
<TextBlock DockPanel.Dock="Left" Text=", "/>
<TextBlock DockPanel.Dock="Left" Text="{Binding Contact.FirstName}"/>
<TextBlock DockPanel.Dock="Right" Text="{Binding Contact.Organization}"/>
</DockPanel>
</Border>
<StackPanel DockPanel.Dock="Bottom" Style="{StaticResource buttonPanel}">
<Button Content="Save" Click="Save_Click"/>
<Button Content="Delete" Click="Delete_Click"/>
<Button Content="Close" Click="Close_Click"/>
</StackPanel>
<WrapPanel>
<GroupBox BorderBrush="{StaticResource lightBlueBrush}">
<GroupBox.Header>
<Border Background="{StaticResource lightBlueBrush}" Style="{StaticResource groupBoxHeader}">
<TextBlock Text="General"/>
</Border>
</GroupBox.Header>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="175"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid Grid.RowSpan="4">
<Border Background="Gray"
CornerRadius="6"
Margin="2 2 0 0"
Opacity=".5"/>
<Border Margin="2 2 4 4"
Background="White"/>
<Viewbox Margin="2 2 4 4">
<Image Source="{Binding Contact.ImagePath}" />
</Viewbox>
<Border BorderBrush="{StaticResource lightBlueBrush}"
BorderThickness="2"
Background="Transparent"
CornerRadius="6"
Margin="0 0 2 2"/>
<Button Style="{StaticResource openButton}"
Background="White"
Foreground="{StaticResource lightBlueBrush}"
BorderBrush="{StaticResource lightBlueBrush}"
ToolTip="Change Picture"
Click="SelectImage_Click" />
</Grid>
<Label Grid.Column="1"
Content="_First Name:"
Target="{Binding ElementName=firstName}"/>
<TextBox x:Name="firstName"
Grid.Column="2"
Text="{Binding Contact.FirstName}"/>
<Label Grid.Row="1"
Grid.Column="1"
Content="_Last Name:"
Target="{Binding ElementName=lastName}"/>
<TextBox x:Name="lastName"
Grid.Row="1"
Grid.Column="2"
Text="{Binding Contact.LastName}"/>
<Label Grid.Row="2"
Grid.Column="1"
Content="Or_ganization:"
Target="{Binding ElementName=organization}"/>
<TextBox x:Name="organization"
Grid.Row="2"
Grid.Column="2"
Text="{Binding Contact.Organization}"/>
<Label Grid.Row="3"
Grid.Column="1"
Content="_Job Title:"
Target="{Binding ElementName=jobTitle}"/>
<TextBox x:Name="jobTitle"
Grid.Row="3"
Grid.Column="2"
Text="{Binding Contact.JobTitle}"/>
</Grid>
</GroupBox>
<GroupBox BorderBrush="{StaticResource greenBrush}">
<GroupBox.Header>
<Border Background="{StaticResource greenBrush}"
Style="{StaticResource groupBoxHeader}">
<TextBlock Text="Address"/>
</Border>
</GroupBox.Header>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="150"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Content="Line _1:"
Target="{Binding ElementName=line1}" />
<TextBox x:Name="line1"
Grid.Column="1"
Grid.ColumnSpan="3"
Text="{Binding Contact.Address.Line1}" />
<Label Grid.Row="1"
Content="Line _2:"
Target="{Binding ElementName=line2}" />
<TextBox x:Name="line2"
Grid.Row="1"
Grid.Column="1"
Grid.ColumnSpan="3"
Text="{Binding Contact.Address.Line2}" />
<Label Grid.Row="2"
Content="Ci_ty:"
Target="{Binding ElementName=city}" />
<TextBox x:Name="city"
Grid.Row="2"
Grid.Column="1"
Text="{Binding Contact.Address.City}" />
<Label Grid.Row="2"
Grid.Column="2"
Content="_State:"
Target="{Binding ElementName=state}" />
<TextBox x:Name="state"
Grid.Row="2"
Grid.Column="3"
Text="{Binding Contact.Address.State}" />
<Label Grid.Row="3"
Grid.Column="0"
Content="_Zip:"
Target="{Binding ElementName=zip}" />
<TextBox x:Name="zip"
Grid.Row="3"
Grid.Column="1"
Text="{Binding Contact.Address.Zip}" />
<Label Grid.Row="3"
Grid.Column="2"
Content="Countr_y:"
Target="{Binding ElementName=country}" />
<TextBox x:Name="country"
Grid.Row="3"
Grid.Column="3"
Text="{Binding Contact.Address.Country}" />
</Grid>
</GroupBox>
<GroupBox BorderBrush="{StaticResource redBrush}">
<GroupBox.Header>
<Border Background="{StaticResource redBrush}"
Style="{StaticResource groupBoxHeader}">
<TextBlock Text="Phone"/>
</Border>
</GroupBox.Header>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="150"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Content="_Office:"
Target="{Binding ElementName=office}"/>
<TextBox x:Name="office"
Grid.Column="1"
Text="{Binding Contact.OfficePhone}" />
<Label Grid.Row="1"
Content="_Cell:"
Target="{Binding ElementName=cell}" />
<TextBox x:Name="cell"
Grid.Row="1"
Grid.Column="1"
Text="{Binding Contact.CellPhone}" />
<Label Grid.Row="2"
Content="_Home:"
Target="{Binding ElementName=home}" />
<TextBox x:Name="home"
Grid.Row="2"
Grid.Column="1"
Text="{Binding Contact.HomePhone}" />
</Grid>
</GroupBox>
<GroupBox BorderBrush="{StaticResource brownBrush}">
<GroupBox.Header>
<Border Background="{StaticResource brownBrush}"
Style="{StaticResource groupBoxHeader}">
<TextBlock Text="Email"/>
</Border>
</GroupBox.Header>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="200"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Content="_Primary:"
Target="{Binding ElementName=primaryEmail}"/>
<TextBox x:Name="primaryEmail"
Grid.Column="1"
Text="{Binding Contact.PrimaryEmail}"/>
<Label Grid.Row="1"
Content="S_econdary:"
Target="{Binding ElementName=secondaryEmail}"/>
<TextBox x:Name="secondaryEmail"
Grid.Row="1"
Grid.Column="1"
Text="{Binding Contact.SecondaryEmail}"/>
</Grid>
</GroupBox>
</WrapPanel>
</DockPanel>
</UserControl>
This is likely your problem:
public class Address : EntityBase
{
[ForeignKey("Contact")] // <---
public int AddressId { get; set; }
along with that you are disposing your DbContext after saving. When the EF DbContext encounters a new entity (Contact) with a related entity that you expect exists but isn't tracked, it will treat that entity as a new entity. This behaviour is likely the root of what is tripping you up passing entities around. The Address is no longer tracked so an existing address record is attempted to be re-inserted and since it is the FK pointing at Contact, it will not generate a new value, but try to use the current ID of the contact.
Typically Address would expect to have a PK (AddressID) and a FK (ContactId) if your contact could have multiple addresses. Either that or the Contact entity would have an AddressID. (Where a single address could serve multiple contacts) If you want one contact to have only one address then either put the address fields into Contact itself, or create a ContactAddressDetails table with a ContactId as the PK+FK for a HasRequired/WithRequired relationship if you want it in a separate table. The desired relationship will define what the fields on the entity / schema will look like.
Thanks for your answers but i found the problem:
public ContactRepository()
{
if (this.GetAll() == null)
{
_contactStore = new List<Contact>();
}
else
{
_contactStore = this.GetAll();
}
}
public List<Contact> GetAll() => Context.Contacts.ToList();
In the ContactRepository constructor after calling GetAll() i have to dispose the current context:
private List<Contact> _contactStore = new List<Contact>();
public ContactRepository()
{
_contactStore = this.GetAll();
Context.Dispose();
Context = new CMEntities();
}
and everything is working fine.
i do not know is there a better solution instead of continuous calling Context.Dispose() or it is the right way?
In my code I have one observable collection that has many combo boxes inside that. Now I have to add List for each combo boxes using MVVM (Model-View-View Model) i.e., No code behind
In View.xaml:
<Window.... xmlns:VM="clr-namespace:myproject.myViewModel"
... >
<Window.DataContext><VM:myViewModel/>
</Window.DataContext>
<ItemsControl ItemsSource="{Binding myCollection}" >
<ItemsControl.ItemTemplate >
<DataTemplate>
<DockPanel>
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Margin="0,20,0,0" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Text="City" Margin="20" VerticalAlignment="Center"/>
<ComboBox KeyboardNavigation.TabIndex="0" Grid.Column="1" Margin="45,10,10,10" Height="30" Width="200" ItemsSource="{Binding City}" />
<TextBlock Text="temperature" Grid.Row="1" VerticalAlignment="Center" Margin="20" />
<ComboBox KeyboardNavigation.TabIndex="3" Grid.Column="1" Grid.Row="1" Margin="45,20,10,10" Height="30" Width="200" SelectedIndex="0" HorizontalContentAlignment="Right"
VerticalAlignment="Center" ItemsSource="{Binding Temperature}">
</ComboBox>
<TextBlock Text="State" Grid.Row="1" VerticalAlignment="Center" Margin="10" Grid.Column="2"/>
<ComboBox KeyboardNavigation.TabIndex="3" Grid.Column="3" Grid.Row="1" Margin="10" Height="30" Width="200" HorizontalContentAlignment="Center" ItemsSource="{Binding State}" >
</ComboBox>
<TextBlock Text="Open Files " VerticalAlignment="Center" Grid.Row="0" Grid.Column="2" Margin="10" />
<TextBox Grid.Column="3" Text="" Height="30" Grid.Row="0" IsReadOnly="True"
TextAlignment="Right" VerticalContentAlignment="Center" Width="200" /> <Button Grid.Column="4" Content="Browse" Height="30" VerticalAlignment="Bottom" MinWidth="41" />
</Grid>
</Window>
In **Model.cs**:
namespace myproject.Models
{
public class projectmodel : INotifyPropertyChanged
{
private ObservableCollection<projectmodel> city;
private ObservableCollection<projectmodel> temperature;
private ObservableCollection<projectmodel> state;
public ObservableCollection<projectmodel> City
{
get { return city; }
set
{
city = value;
NotifyPropertyChanged("City");
}
}
public ObservableCollection<projectmodel> Temperature
{
get { return temperature; }
set
{
temperature = value;
NotifyPropertyChanged("Temperature");
}
}
public ObservableCollection<projectmodel> State
{
get { return state; }
set
{
state = value;
NotifyPropertyChanged("State");
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
#region Private Helpers
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}}
In ViewModel.cs:
namespace myproject.ViewModels
{
public class projectViewModel
{
public ObservableCollection<T> myCollection
{
get; set;
}
public projectViewModel()
{
myCollection = new ObservableCollection<T>();
List<string> lstCity = new List<string>();
lstCity = new List<string> { "Coimbatore", "Chennai", "Bangalore" };
List<string> lstTemperature = new List<string>();
lstTemperature = new List<string> { "17c", "18c", "15c" };
List<string> lstState = new List<string>();
lstState = new List<string> { "Andhra", "karnataka", "TamilNadu" };
}
}myCollection.Add(new projectmodel
{
City = lstCity.ToArray(),
Temperature = lstTemperature.ToArray(),
State= lstState.ToArray()
});
}
}}
This is my code,I didn't get anything if I select my combo boxes. Please suggest me how should I write my viewmodel.cs ,and also correct me if I'm wrong anywhere else.
You have to declare all your collections inside your projectmodel to be of type ObservableCollection<string> instead of sting[]. When ever you bind to a collection use ObservableCollection<T>.
Your view models must also all implement INotifyPropertyChanged
Changes:
ProjectModel:
namespace Myproject.Models
{
public class ProjectModel : INotifyPropertyChanged
{
private ObservableCollection<string> city;
private ObservableCollection<string> temperature;
private ObservableCollection<string> state;
public ObservableCollection<string> City
{
get { return city; }
set
{
city = value;
NotifyPropertyChanged("City");
}
}
public ObservableCollection<string> Temperature
{
get { return temperature; }
set
{
temperature = value;
NotifyPropertyChanged("Temperature");
}
}
public ObservableCollection<string> State
{
get { return state; }
set
{
state = value;
NotifyPropertyChanged("State");
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
#region Private Helpers
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
}
ProjectViewModel:
namespace MyProject.ViewModels
{
public class ProjectViewModel : INotifyPropertyChanged
{
private ObservableCollection<Projectmodel> myCollection;
public ObservableCollection<Projectmodel> MyCollection
{
get => this.myCollection;
set
{
if (Equals(value, this.myCollection)) return;
this.myCollection = value;
OnPropertyChanged();
}
}
public ProjectViewModel()
{
MyCollection = new ObservableCollection<Projectmodel>()
{
new ProjectModel()
{
City = new ObservableCollection<string>()
{
"Coimbatore", "Chennai", "Bangalore"
},
Temperature = new ObservableCollection<string>()
{
"17c", "18c", "15c"
},
State = new ObservableCollection<string>()
{
"Andhra", "karnataka", "TamilNadu"
}
}
};
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Edit:
I updated the code to meet the common naming conventions using PascalCase. It is recommended to follow them: C# Conventions
When developing MVVP program i collide with some problem based on unsensibility of class when it's properties changed.
For example we have base class Brick, that have properties inditating Number of Holes and Cracks in it.
class Class_Brick : DependencyObject
{
public Class_Brick()
{
}
#region DependencyProperties
public static DependencyProperty NumberOfHoles_Property = DependencyProperty.Register("NumberOfHoles", typeof(int), typeof(Class_Brick),
new FrameworkPropertyMetadata()
{
DefaultValue = 0,
BindsTwoWayByDefault = true,
DefaultUpdateSourceTrigger = System.Windows.Data.UpdateSourceTrigger.PropertyChanged
});
public static DependencyProperty NumberOfCracks_Property = DependencyProperty.Register("NumberOfCracks", typeof(int), typeof(Class_Brick),
new FrameworkPropertyMetadata()
{
DefaultValue = 0,
BindsTwoWayByDefault = true,
DefaultUpdateSourceTrigger = System.Windows.Data.UpdateSourceTrigger.PropertyChanged
});
#endregion
#region Properties
public int NumberOfHoles
{
get { return (int)GetValue(NumberOfHoles_Property); }
set { SetValue(NumberOfHoles_Property, value); }
}
public int NumberOfCracks
{
get { return (int)GetValue(NumberOfCracks_Property); }
set { SetValue(NumberOfCracks_Property, value); }
}
#endregion
}
Class Wall has collection of Bricks and Standard Brick (put both in DependencyProperty is not obligatory - only to demonstrate needed callback).
Also Wall has same properties as Brick that calculate Number of Cracks and Holes in collection of Bricks and Standard Brick. Tey must calculate every time, when changed parametres in Standard Brick or changed collection (add item, remove item or changed parametres in item).
class Class_Wall : DependencyObject
{
public Class_Wall()
{
SetValue(Standard_Brick_Property, new Class_Brick());
SetValue(Bricks_Property, new ObservableCollection<Class_Brick>());
}
#region DependencyProperties
public static DependencyProperty NumberOfHoles_Property = DependencyProperty.Register("NumberOfHoles", typeof(int), typeof(Class_Wall),
new FrameworkPropertyMetadata()
{
DefaultValue = 0,
BindsTwoWayByDefault = true,
DefaultUpdateSourceTrigger = System.Windows.Data.UpdateSourceTrigger.PropertyChanged
});
public static DependencyProperty NumberOfCracks_Property = DependencyProperty.Register("NumberOfCracks", typeof(int), typeof(Class_Wall),
new FrameworkPropertyMetadata()
{
DefaultValue = 0,
BindsTwoWayByDefault = true,
DefaultUpdateSourceTrigger = System.Windows.Data.UpdateSourceTrigger.PropertyChanged
});
public static DependencyProperty Standard_Brick_Property = DependencyProperty.Register("Standard_Brick", typeof(Class_Brick), typeof(Class_Wall),
new FrameworkPropertyMetadata()
{
BindsTwoWayByDefault = true,
DefaultUpdateSourceTrigger = System.Windows.Data.UpdateSourceTrigger.PropertyChanged,
PropertyChangedCallback = new System.Windows.PropertyChangedCallback(On_Property_Change)
});
public static DependencyProperty Bricks_Property = DependencyProperty.Register("Bricks", typeof(ObservableCollection<Class_Brick>), typeof(Class_Wall),
new FrameworkPropertyMetadata()
{
BindsTwoWayByDefault = true,
DefaultUpdateSourceTrigger = System.Windows.Data.UpdateSourceTrigger.PropertyChanged,
PropertyChangedCallback = new System.Windows.PropertyChangedCallback(On_Property_Change)
});
#endregion
#region Inner Methods
public static void On_Property_Change(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ObservableCollection<Class_Brick> inWall;
int wallCracks = 0;
int wallHoles = 0;
if (e.Property == Bricks_Property)
{
inWall = e.NewValue as ObservableCollection<Class_Brick>;
Class_Brick mainItem = (Class_Brick)d.GetValue(Standard_Brick_Property);
wallCracks = mainItem.NumberOfCracks;
wallHoles = mainItem.NumberOfHoles;
}
else //if (e.Property == Standard_Brick_Property)
{
inWall = (ObservableCollection<Class_Brick>)d.GetValue(Bricks_Property);
Class_Brick newItem = e.NewValue as Class_Brick;
wallCracks = newItem.NumberOfCracks;
wallHoles = newItem.NumberOfHoles;
}
if (inWall != null)
{
foreach (Class_Brick brick in inWall)
{
wallCracks += brick.NumberOfCracks;
wallHoles += brick.NumberOfHoles;
}
d.SetValue(Home_Quest.Class_Wall.NumberOfCracks_Property, wallCracks);
d.SetValue(Home_Quest.Class_Wall.NumberOfHoles_Property, wallHoles);
}
}
#endregion
#region Properties
public int NumberOfHoles
{
get { return (int)GetValue(NumberOfHoles_Property); }
}
public int NumberOfCracks
{
get { return (int)GetValue(NumberOfCracks_Property); }
}
public Class_Brick Standard_Brick
{
get { return (Class_Brick)GetValue(Standard_Brick_Property); }
set { SetValue(Standard_Brick_Property, value); }
}
public ObservableCollection<Class_Brick> Bricks
{
get { return (ObservableCollection<Class_Brick>)GetValue(Bricks_Property); }
set { SetValue(Bricks_Property, value); }
}
#endregion
}
I used this XAML for the test field:
<DockPanel LastChildFill="True">
<TextBlock Text="Wall"
DockPanel.Dock="Top"
HorizontalAlignment="Center"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<DockPanel Grid.Column="0"
Grid.Row="0" Grid.RowSpan="2"
LastChildFill="True">
<TextBlock Text="Bricks"
DockPanel.Dock="Top" />
<Button Content="-" DockPanel.Dock="Bottom"
Click="btn_Remove" />
<Button Content="+" DockPanel.Dock="Bottom"
Click="btn_Add" />
<ListBox x:Name="lB_Bricks"
ItemsSource="{Binding Path=Bricks}"
HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Margin="2"
BorderBrush="Azure"
BorderThickness="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Text="Holes"
Grid.Column="0" Grid.Row="0"/>
<TextBox Text="{Binding Path=NumberOfHoles, Mode=TwoWay}"
Grid.Column="1" Grid.Row="0"
TextAlignment="Center"/>
<TextBlock Text="Cracks"
Grid.Column="0" Grid.Row="1"/>
<TextBox Text="{Binding Path=NumberOfCracks, Mode=TwoWay}"
Grid.Column="1" Grid.Row="1"
TextAlignment="Center"/>
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DockPanel>
<DockPanel Grid.Column="1"
Grid.Row="0"
LastChildFill="True"
DataContext="{Binding Path=Standard_Brick}">
<TextBlock Text="Standard Brick"
DockPanel.Dock="Top" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Text="Holes"
Grid.Column="0" Grid.Row="0"/>
<TextBox Text="{Binding Path=NumberOfHoles, Mode=TwoWay}"
Grid.Column="1" Grid.Row="0"
TextAlignment="Center"/>
<TextBlock Text="Cracks"
Grid.Column="0" Grid.Row="1"/>
<TextBox Text="{Binding Path=NumberOfCracks, Mode=TwoWay}"
Grid.Column="1" Grid.Row="1"
TextAlignment="Center"/>
</Grid>
</DockPanel>
<DockPanel Grid.Column="1"
Grid.Row="1"
LastChildFill="True">
<TextBlock Text="Resulted Cracks and Holes"
DockPanel.Dock="Top" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Text="Holes"
Grid.Column="0" Grid.Row="0"/>
<TextBox Text="{Binding Path=NumberOfHoles}"
Grid.Column="1" Grid.Row="0"
IsReadOnly="True"
TextAlignment="Center"/>
<TextBlock Text="Cracks"
Grid.Column="0" Grid.Row="1"/>
<TextBox Text="{Binding Path=NumberOfCracks}"
Grid.Column="1" Grid.Row="1"
IsReadOnly="True"
TextAlignment="Center"/>
</Grid>
</DockPanel>
</Grid>
</DockPanel>
and code for MainWindow.cs:
public MainWindow()
{
InitializeComponent();
this.DataContext = currentWall;
}
Class_Wall currentWall = new Class_Wall();
private void btn_Add(object sender, RoutedEventArgs e)
{
currentWall.Bricks.Add(new Class_Brick());
}
private void btn_Remove(object sender, RoutedEventArgs e)
{
Class_Brick selectedBrick = this.lB_Bricks.SelectedItem as Class_Brick;
if ( selectedBrick != null)
{
currentWall.Bricks.Remove(selectedBrick);
}
}
Until today, I never got to find the solution for this problem, using DependencyProperties.
Hope for your help and support.
Well, INotifyPropertyChanged helps solve my problem.
Here some code for updated Classes Brick:
class Class_Brick_NPC : INotifyPropertyChanged
{
public Class_Brick_NPC()
{
}
#region Event Functions
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if(handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
#endregion
#region Inner Parametres
private int numberOfHoles = 0;
private int numberOfCracks = 0;
#endregion
#region Parametres
public int NumberOfHoles
{
get { return numberOfHoles; }
set
{
numberOfHoles = value;
OnPropertyChanged("NumberOfHoles");
}
}
public int NumberOfCracks
{
get { return numberOfCracks; }
set
{
numberOfCracks = value;
OnPropertyChanged("NumberOfCracks");
}
}
#endregion
}
and Wall:
class Class_Wall_NPC : INotifyPropertyChanged
{
public Class_Wall_NPC()
{
standard_Brick.PropertyChanged += InnerUpdate;
}
#region Event Methods
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
public void InnerUpdate(object sender, PropertyChangedEventArgs args)
{
if (args.PropertyName == "NumberOfHoles")
{
OnPropertyChanged("NumberOfHoles");
}
else if (args.PropertyName == "NumberOfCracks")
{
OnPropertyChanged("NumberOfCracks");
}
}
#endregion
#region Inner Properties
private ObservableCollection<Class_Brick_NPC> bricks = new ObservableCollection<Class_Brick_NPC>();
private Class_Brick_NPC standard_Brick = new Class_Brick_NPC();
private int numberOfHoles = 0;
private int numberOfCracks = 0;
#endregion
#region Properties
public ObservableCollection<Class_Brick_NPC> Bricks
{
get { return bricks; }
set
{
bricks = value;
OnPropertyChanged("Bricks");
}
}
public Class_Brick_NPC Standard_Brick
{
get { return standard_Brick; }
set
{
standard_Brick = value;
}
}
public int NumberOfHoles
{
get
{
int wallHoles = standard_Brick.NumberOfHoles;
foreach (Class_Brick_NPC brick in bricks)
{
wallHoles += brick.NumberOfHoles;
}
return wallHoles;
}
}
public int NumberOfCracks
{
get
{
int wallCracks = standard_Brick.NumberOfCracks;
foreach (Class_Brick_NPC brick in bricks)
{
wallCracks += brick.NumberOfCracks;
}
return wallCracks;
}
}
#endregion
#region Methods
public void Add_Brick(Class_Brick_NPC addedItem)
{
bricks.Add(addedItem);
addedItem.PropertyChanged += InnerUpdate;
OnPropertyChanged("Bricks");
}
public void Remove_Brick(Class_Brick_NPC removedItem)
{
bricks.Remove(removedItem);
removedItem.PropertyChanged -= InnerUpdate;
OnPropertyChanged("Bricks");
OnPropertyChanged("NumberOfHoles");
OnPropertyChanged("NumberOfCracks");
}
#endregion
}
But is there any way to achieve same result using DependencyProperty?
I'm trying to display a model and I want to save it when the user clicks a button.
(Bind ModelView OneWay to Model and if the save button was pressed I update the source manually.)
Is that possible?
Here I created a small example with my problem. (not MVVM!)
MainWindow.xaml
<Grid>
<Grid.DataContext>
<ViewModel:MainViewModel/>
</Grid.DataContext>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<local:PersonListView Grid.Column="0" DataContext="{Binding ViewModel_PersonList}"/>
<local:PersonView Grid.Column="1" DataContext="{Binding ViewModel_Person}"/>
</Grid>
PersonListView.xaml
<ListView ItemsSource="{Binding PersonList}" SelectedItem="{Binding SelectedPerson}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding LastName}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
PersonView.xaml
<Grid DataContext="{Binding}">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<TextBlock Text="First Name:" Grid.Column="0" Grid.Row="0" Margin="5"/>
<TextBlock Text="Last Name:" Grid.Column="0" Grid.Row="1" Margin="5"/>
<TextBlock Text="Age:" Grid.Column="0" Grid.Row="2" Margin="5"/>
<TextBox Text="{Binding Path=Person.FirstName, UpdateSourceTrigger=Explicit}" Grid.Column="1" Grid.Row="0" Margin="5"/>
<TextBox Text="{Binding Path=Person.LastName, UpdateSourceTrigger=Explicit}" Grid.Column="1" Grid.Row="1" Margin="5"/>
<TextBox Text="{Binding Path=Person.Age, UpdateSourceTrigger=Explicit}" Grid.Column="1" Grid.Row="2" Margin="5"/>
<Button Content="Save" Command="{Binding SaveCommand}" Grid.Column="1" Grid.Row="4"/>
</Grid>
Person.cs
public class Person : INotifyPropertyChanged
{
private string firstName;
public string FirstName
{
get { return firstName; }
set
{
firstName = value;
OnPropertyChanged("FirstName");
}
}
private string lastName;
public string LastName
{
get { return lastName; }
set
{
lastName = value;
OnPropertyChanged("LastName");
}
}
private int age;
public int Age
{
get { return age; }
set
{
age = value;
OnPropertyChanged("Age");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
MainViewModel.cs
public class MainViewModel : ViewModelBase
{
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public MainViewModel()
{
ViewModel_PersonList.PersonList.Add(new Model.Person()
{
LastName = "Test",
FirstName = "John",
Age = 20
});
ViewModel_PersonList.PersonList.Add(new Model.Person()
{
LastName = "Example",
FirstName = "Luke",
Age = 25
});
ViewModel_PersonList.SelectedPerson = ViewModel_PersonList.PersonList[1];
ViewModel_Person.Person = ViewModel_PersonList.SelectedPerson;
}
ViewModel.PersonViewModel _ViewModel_Person = new ViewModel.PersonViewModel();
public ViewModel.PersonViewModel ViewModel_Person
{
get
{
return _ViewModel_Person;
}
set
{
_ViewModel_Person = value;
RaisePropertyChanged("ViewModel_Person");
}
}
ViewModel.PersonListViewModel _ViewModel_PersonList = new ViewModel.PersonListViewModel();
public ViewModel.PersonListViewModel ViewModel_PersonList
{
get
{
return _ViewModel_PersonList;
}
set
{
_ViewModel_PersonList = value;
RaisePropertyChanged("ViewModel_PersonList");
}
}
}
PersonListViewModel.css
public class PersonListViewModel : ViewModelBase
{
ObservableCollection<Model.Person> _PersonList = new ObservableCollection<Model.Person>();
public ObservableCollection<Model.Person> PersonList
{
get
{
return _PersonList;
}
set
{
_PersonList = value;
RaisePropertyChanged("PersonList");
}
}
Model.Person _SelectedPerson = new Model.Person();
public Model.Person SelectedPerson
{
get
{
return _SelectedPerson;
}
set
{
MessengerInstance.Send<Model.Person>(value);
_SelectedPerson = value;
RaisePropertyChanged("SelectedPerson");
}
}
}
PersonViewModel.cs
public class PersonViewModel : ViewModelBase
{
public PersonViewModel()
{
MessengerInstance.Register<Model.Person>(this, per => Person = per);
}
Model.Person _Person = new Model.Person();
public Model.Person Person
{
get
{
return _Person;
}
set
{
_Person = value;
RaisePropertyChanged("Person");
}
}
private RelayCommand<Model.Person> _SaveCommand;
public ICommand SaveCommand
{
get
{
if (_SaveCommand == null)
_SaveCommand = new RelayCommand<Model.Person>(SaveCommand_Execute, SaveCommand_CanExecute);
return _SaveCommand;
}
}
private bool SaveCommand_CanExecute(Model.Person newPerson)
{
return true;
}
private void SaveCommand_Execute(Model.Person newPerson)
{
// Do my saving!
}
}
Thank you!
You can make the Mode=TwoWay and use UpdateSourceTrigger=Explicit. Refer below code.
<StackPanel>
<TextBox Name="tb_1" Text="HelloWorld!"/>
<TextBox Name="tb_2" Text="{Binding Path=Text, ElementName=tb_1, Mode=TwoWay,UpdateSourceTrigger=Explicit}"/>
<Button Content="Update Source" Click="Button_Click"/>
</StackPanel>
i've a problem to use datagrid in wpf mvvm project
Here is my xaml :
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors"
x:Class="noteManager.MainWindow"
xmlns:vm="clr-namespace:noteManager.ViewModel"
DataContext="{StaticResource noteManagerViewModel}"
Title="NoteManager" Height="490" Width="525">
<Grid Margin="0,0,0,-132.5">
<Grid.RowDefinitions>
<RowDefinition Height="10"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition Height="200"></RowDefinition>
<RowDefinition Height="40"></RowDefinition>
<RowDefinition Height="110"></RowDefinition>
<RowDefinition Height="111"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="80"></ColumnDefinition>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="80"></ColumnDefinition>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Text="Login :" FontSize="16" Grid.Column="2" Margin="51,9,50,0" Grid.RowSpan="2" Height="23" VerticalAlignment="Top" Grid.ColumnSpan="2"/>
<TextBox Text="{Binding Login}" Grid.Row="1" Grid.Column="3" Margin="14,0,86,29" Grid.ColumnSpan="2"/>
<Button Background="LightGreen" Foreground="Green" Command="{Binding testConnexion}" x:Name="testConnexion" Content="Connexion" Grid.Row="1" Grid.Column="2" Margin="51,29,86,0" Grid.ColumnSpan="3"/>
<Button Command="{Binding addUser}" Content="+" Grid.Row="1" Grid.Column="4" Margin="34,1,20,0" RenderTransformOrigin="0.742,0.468"/>
<DataGrid Name="dataGrid1" Grid.Row="2" Margin="8,7,-22,7" AutoGenerateColumns="False"
ItemsSource="{Binding _DataGridNotes}" SelectedItem="{Binding Path=MySelectedNote}" HorizontalAlignment="Center"
Width="480" Grid.ColumnSpan="6" Grid.Column="1">
<DataGrid.Columns>
<DataGridTextColumn Width="100" Binding="{Binding Path=NoteTitle}" Header="Titre" />
<DataGridTextColumn Width="200" Binding="{Binding Path=NoteContent}" Header="Note" />
<DataGridTextColumn Width="100" Binding="{Binding Path=NoteCreatedAt}" Header="Date de création" />
<DataGridTextColumn Width="100" Binding="{Binding Path=NoteUpdatedAt}" Header="Dat MAJ" />
</DataGrid.Columns>
</DataGrid>
<TextBlock Text="Titre" FontSize="16" Grid.Row="3" Grid.Column="1" Margin="27,8,7,1"/>
<TextBox Text="{Binding Path=titre, Mode=TwoWay}" Grid.Row="3" Grid.Column="2" Margin="17,10,23,10" Grid.ColumnSpan="5"/>
<TextBlock Text="Note" FontSize="16" Grid.Row="4" Grid.Column="1" Margin="27,4,7,0"/>
<TextBox Text="{Binding Path=description, Mode=TwoWay}" Grid.Row="4" Grid.Column="2" Margin="17,10,23,8" Grid.ColumnSpan="5"/>
<Button Command="{Binding Path=DeleteNote}" Background="LightPink" Foreground="red" Content="Supprimer" Grid.Row="5" Grid.Column="1" Margin="55,7,26,81" Grid.ColumnSpan="2"/>
<Button Command="{Binding Path=UpdateANote}" Content="Mettre à jour" Grid.Row="5" Grid.Column="3" Margin="14,7,67,81" Grid.ColumnSpan="2" RenderTransformOrigin="0.5,0.5"/>
<Button Command="{Binding Path=AddNote}" Content="Ajouter" Grid.Row="5" Grid.Column="4" Margin="78,7,10,81" Grid.ColumnSpan="3"/>
</Grid>
</Window>
Here is my viewModel :
namespace noteManager.ViewModel
{
public class noteManagerViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
void Notify(string property)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
string login;
int currentUser;
public string Login
{
get
{
return login;
}
set
{
login = value; Notify("Login");
}
}
private bool _canExecute;
public noteManagerViewModel()
{
_canExecute = true;
}
private ICommand _testConnexion;
public ICommand testConnexion
{
get
{
return _testConnexion ?? (_testConnexion = new CommandHandler(() => Connexion(), _canExecute));
}
}
private ICommand _addUser;
public ICommand addUser
{
get
{
return _addUser ?? (_addUser = new CommandHandler(() => AjoutUser(), _canExecute));
}
}
private ObservableCollection<DataGridNotes> _DataGridNotes = new ObservableCollection<DataGridNotes>();
public ObservableCollection<DataGridNotes> dataGridNotes
{
// No need for a public setter
get { return _DataGridNotes; }
}
}
the other class that i use :
public class User
{
/*public User()
{
this.Note = new HashSet<Note>();
}*/
public int Id { get; set; }
public string Login { get; set; }
//public virtual ICollection<Note> Note { get; set; }
}
public class Note : INotifyPropertyChanged
{
public int Id { get; set; }
public string NoteText { get; set; }
public string ContentText { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime? UpdatedAt { get; set; }
public int UserId { get; set; }
//public virtual User User { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public void Notify(string property)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
public class DataGridNotes
{
private string _noteTitle;
private string _noteContent;
private string _noteCreatedAt;
private string _noteUpdatedAt;
public string NoteTitle { get { return _noteTitle; } set { _noteTitle = value; } }
public string NoteContent { get { return _noteContent; } set { _noteContent = value; } }
public string NoteCreatedAt { get { return _noteCreatedAt; } set { _noteCreatedAt = value; } }
public string NoteUpdatedAt { get { return _noteUpdatedAt; } set { _noteUpdatedAt = value; } }
}
sorry for the ugly code, new to c# for a project.
i want to use the datagrid in my viewmodel but don't find a way to make it work (would like to write data from mysql database in the datagrid
Have you an idea to make it work ?
thx in advance
Ok, It's tough to spot what you are doing wrong without seeing the ViewModel, however you may want to check the following:
1) The DataContext is correct.
2) The property _DataGridNotes exists. Check the program output to make sure that there are no warnings informing you that bindings are broken.
The property you are looking to have should look something like this:
List<Note> _DataGridNotes
{
get
{
// get notes from SQL request
// construct list of Note and return list
}
}
You should also make sure that the Note class contains the properties required (NoteTitle, NoteContent, NoteCreatedAt, NoteUpdatedAt).
It might also be worth passing back some dummy notes to debug if the problem lies in the request to the SQL database.
The problem is that you are trying to bind to a private Observable collection _DataGridNotes where you should be binding to the property dataGridNotes:
ItemsSource="{Binding dataGridNotes}"