MVVM get value from datagrid - c#

I used MVVM.
How I can get the selected item from DataGrid?
It is my Model
Person.cs
public class Person : INotifyPropertyChanged
{
#region Fields
private string _firstName;
private string _middleName;
private string _lastName;
private DateTime _dateOfBirth;
private Gender _gender;
#endregion Fields
#region Properties
public string FirstName
{
get { return _firstName; }
set
{
if (value == _firstName) return;
_firstName = value;
nPropertyChanged();
}
}
public string MiddleName
{
get { return _middleName; }
set
{
if (value == _middleName) return;
_middleName = value;
OnPropertyChanged();
}
}
public string LastName
{
get { return _lastName; }
set
{
if (value == _lastName) return;
_lastName = value;
OnPropertyChanged();
}
}
public DateTime DateOfBirth
{
get { return _dateOfBirth; }
set
{
if (value.Equals(_dateOfBirth)) return;
_dateOfBirth = value;
OnPropertyChanged();
}
}
public Gender Gender
{
get { return _gender; }
set
{
if (value == _gender) return;
_gender = value;
OnPropertyChanged();
}
}
#endregion Properties
#region Constructors
public Person()
{
}
public Person(string firstName, string middleName, string lastName, DateTime dateOfBirth, Gender gender)
{
FirstName = firstName;
MiddleName = middleName;
LastName = lastName;
DateOfBirth = dateOfBirth;
Gender = gender;
}
#endregion Constructors
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
//[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion INotifyPropertyChanged
}
public enum Gender
{
Male,
Female
}
}
It is my ViewModel
Ii is PersonsViewModel
namespace Learn.MVVM.Example.ViewModels
{
public class PersonsViewModel<TViewType> : INotifyPropertyChanged, IViewModel where TViewType : IView, new()
{
private readonly IView _view;
private readonly PersonModel _model;
public ObservableCollection<Person> Persons { get; set; }
public RelayCommand OkCommand { get; private set; }
private string _str;
public PersonsViewModel()
{
this._view = new TViewType();
this._model = new PersonModel();
this.Persons = new ObservableCollection<Person>(this._model.GetPersons());
this.OkCommand = new RelayCommand(o => this.OKRun());
_str = "Кнопка";
this._view.SetDataContext(this);
this._view.ShowView();
}
public string Str
{
get { return _str; }
set
{
if (_str == value)
return;
_str = value;
OnPropertyChanged("Str");
}
}
public ObservableCollection<Person> Observ
{
get { return Persons; }
set
{
if (Persons == value)
return;
Persons = value;
OnPropertyChanged("Observ");
}
}
public event PropertyChangedEventHandler PropertyChanged;
//[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
private void OKRun()
{
Str = "Refresh";
//this.Persons = new ObservableCollection<Person>(this._model.SetPersons());
this.Observ = new ObservableCollection<Person>(this._model.SetPersons());
//OnPropertyChanged("Observ");
}
}
}
How i can get value current row from datagrid?
How i can get index current row from datagrid?

In my experience, a nice method to achieve this is by binding the SelectedItem to a property in your view model:
public Person SelectedPerson { get; set; }
And your DataGrid will look like this:
<DataGrid SelectedItem="{Binding SelectedPerson}" ... >

Related

List not being filled by Json deserialize? C#

i'm having difficulties deserialising a json file. The json object has the following structure which has been simplified
{"date":"2015-11-11",
"retailer_id":"CLD001",
"orders":[{
"products":
[{
"product_id":"53743443003",
"quantity":4,"
unit_price":42.71}],
"value":170.84,
"customer":{"id":58}}]}
This structure indicated to me that the top class is
[Table]
public class RetailOrders : INotifyPropertyChanged, INotifyPropertyChanging
{
private List<OrderItems> oi;
private string retailer_id;
private DateTime date;
public List<OrderItems> OrderItems
{
get { return oi; }
set { oi = value; }
}
public string Retailer_id
{
get { return retailer_id; }
set { retailer_id = value; }
}
public DateTime Date
{
get { return date; }
set { date = value; }
}
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
}
}
private void NotifyPropertyChanging(string propertyName)
{
if (PropertyChanging != null)
{
PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public event PropertyChangingEventHandler PropertyChanging;
}
As you can see orders take a list of products being ordered with the variable id, quantity and total price
[Table]
public class ProductsOrdered: INotifyPropertyChanged, INotifyPropertyChanging
{
private string productID;
private int quantity;
private double unit_price;
public string ProductID
{
get { return productID; }
set { productID = value; }
}
public int Quantity
{
get { return quantity; }
set { quantity = value; }
}
public double UnitPrice
{
get { return unit_price; }
set { unit_price = value; }
}
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
}
}
private void NotifyPropertyChanging(string propertyName)
{
if (PropertyChanging != null)
{
PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
}
}
finally the orderItems contain a list of the orders followed by a total price and associated customer
[Table]
public class OrderItems : INotifyPropertyChanged, INotifyPropertyChanging
{
private List<ProductsOrdered> po = new List<ProductsOrdered>();
private double TotalPrice;
private int customer_id;
public List<ProductsOrdered> Productsordered
{
get { return po; }
set { po = value; }
}
public double totalprice
{
get { return TotalPrice; }
set { TotalPrice = value; }
}
public int customerid
{
get { return customer_id; }
set { customer_id = value; }
}
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
}
}
private void NotifyPropertyChanging(string propertyName)
{
if (PropertyChanging != null)
{
PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
public event PropertyChangingEventHandler PropertyChanging;
}
I'm expecting the list to fill out however currently they are null values and can't seem to think of why this is happening
Your property names don't match the JSON you've supplied. Specifically in your JSON there is an array orders but in your C# class the property is OrderItems.
You could annotate the property like this:
[JsonProperty(PropertyName = "orders")]
public List<OrderItems> OrderItems { get; set; }
I haven't worked all the way through your hierarchy, but any other null fields will likely be caused by a similar mismatch.
One other thing to be careful of is private properties and private setters, which I don't thing will be an issue for you here, but is the other top reason for null values when you deserialize JSON.

Force Binding isn't what I want

My oneway binding isn't working as I'm expecting.
When I click a button to add a new "person" it doesn't add the newly entered person to the listview until I shut it down and restart the application (so the value gets added to the DB just not to the UI)
What am I doing incorrectly? I have the INotifyPropertyChanged, I have the ObservableCollection... What am I missing?
I have my Model:
public class Person : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _personName;
private string _personEmail;
private string _personPhone;
private DateTime _personDOB;
[PrimaryKey, AutoIncrement]
public int personId { get; set; }
[MaxLength(25)]
public string personName {
get { return _personName; }
set
{
_personName = value;
OnPropertyChanged("personName");
}
}
[MaxLength(50)]
public string personEmail {
get { return _personEmail; }
set
{
_personEmail = value;
OnPropertyChanged("personEmail");
}
}
[MaxLength(13)]
public string personPhone {
get { return _personPhone; }
set
{
_personPhone = value;
OnPropertyChanged("personPhone");
}
}
public DateTime personDOB {
get { return _personDOB;}
set
{
_personDOB = value;
OnPropertyChanged("personDOB");
}
}
public Boolean isPersonActive { get; set; }
public string Summary
{
get { return string.Format("{0} - {1} : {2} -- {3}", personName, personEmail, personPhone, personDOB); }
}
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
In my ViewModel I have this:
public class ChoresVM
{
private ObservableCollection<win8Chores.Model.databaseTables.Person> _personList;
public ObservableCollection<win8Chores.Model.databaseTables.Person> personList
{
get { return _personList; }
set { _personList = value; }
}
...
public ObservableCollection<win8Chores.Model.databaseTables.Person> selectAllPerson()
{
using (var db = new SQLiteConnection(dbPath))
{
ObservableCollection<win8Chores.Model.databaseTables.Person> pList = new ObservableCollection<win8Chores.Model.databaseTables.Person>(db.Query<win8Chores.Model.databaseTables.Person>("select personId,personName,personEmail,personDOB from Person"));
_personList = new ObservableCollection<Model.databaseTables.Person>(db.Query<win8Chores.Model.databaseTables.Person>("select personId,personName,personEmail,personDOB from Person"));
return _personList;
}
}
public void insertPerson(string name, string email, string phone, DateTime dob, Boolean isActive = true)
{
dbPath = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "myDB");
db = new SQLiteConnection(dbPath);
using (db)
{
var p = db.Insert(new win8Chores.Model.databaseTables.Person()
{
personName = name,
personEmail = email,
personPhone = phone,
personDOB = dob,
isPersonActive = isActive
});
}
selectAllPerson();
}
Then in my View:
public MainPage()
{
this.InitializeComponent();
VM = new ViewModel.ChoresVM();
DataContext = VM;
}
private void btnAdd_Click(object sender, RoutedEventArgs e)
{
DateTime myDOB = new DateTime(1955, 02, 28);
VM.insertPerson("test","test#live.com","123-456-7890", myDOB);
}
With my XAML like this:
<ListView HorizontalAlignment="Left" Height="224" Margin="287,344,0,0" VerticalAlignment="Top" Width="740" x:Name="test" DisplayMemberPath="Summary" ItemsSource="{Binding personList, Mode=OneWay}" />
Try to implement INotifyPropertyChanged on ChoresVM and raise PropertyChanged("personList") when you initialize the collection (in selectAllPerson() or personList setter). This way itemssource binding will be notified, that collection property was changed and will pickup new collection. Also you have a typo. In Binding you have "PersonList" (Pascal case) but you property is in camel case (personList)

listbox data binding fails silently

This approach seems to work half the time for me.
I can see these lines get executed in the debugger:
agencyListBox.DataBindings.Add(new Binding("DataSource", this.Data.Agencies, "AvailableAgencies"));
agencyListBox.DataBindings.Add(new Binding("SelectedItem", this.Data.Agencies, "SelectedAgency", false, DataSourceUpdateMode.OnPropertyChanged));
The agencies class looks like this:
public AgencyType SelectedAgency
{
get
{
return _selected;
}
set
{
_selected = value;
OnPropertyChanged("SelectedAgency");
}
}
public List<AgencyType> AvailableAgencies
{
get
{
return _availableList;
}
set
{
_availableList = value;
OnPropertyChanged("AvailableAgencies");
}
}
So the fields I reference in the binding do exist.
The DisplayMember is set to "Label" which is defined in the AgencyType class:
public event PropertyChangedEventHandler PropertyChanged;
private string _label { get; set; }
public string Label
{
get { return _label; }
set
{
_label = value;
OnPropertyChanged("Label");
}
}
private string _identifier { get; set; }
public string Identifier
{
get { return _identifier; }
set
{
_identifier = value;
OnPropertyChanged("Identifier");
}
}
public AgencyType()
{
Label = string.Empty;
Identifier = string.Empty;
}
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
The values are displayed as desired.
But then when I change the selection, data.Agencies.SelectedAgency is null!
Does anyone have any tips?

TextBox binding not initialising

I'm have a TextBox which gets added to a Window alongside a Checkbox. I've managed to bind the TextBox to property Order of the CheckedListItem handler so when a change is made it binds correctly and updates.
My problem I'm having is that I cannot get it to initialise with starting values. My constructor is as follows
public partial class OwnerSettingWindow : Window
{
public ObservableCollection<CheckedListItem<Owner>> Owners { get; set; }
public class Owner
{
public String OwnerName { get; set; }
public String OwnerOrder { get; set; }
}
public OwnerSettingWindow()
{
InitializeComponent();
Owners = new ObservableCollection<CheckedListItem<Owner>>();
string testString = #"Item1,true,1:Item2,true,2:Item3,false,24"; ;
string[] splitOwners = testString.Split(':');
foreach (string item in splitOwners)
{
string[] spOwnerSetting = item.Split(',');
bool bchecked = bool.Parse(spOwnerSetting[1].ToString());
string norder = spOwnerSetting[2].ToString();
Owners.Add(new CheckedListItem<Owner>(new Owner() { OwnerName = spOwnerSetting[0].ToString(), OwnerOrder = norder },
isChecked: bchecked));
}
DataContext = this;
}
public class CheckedListItem<T> : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private bool isChecked;
private T item;
private string order;
public CheckedListItem()
{ }
public CheckedListItem(T item, bool isChecked = false)
{
this.item = item;
this.isChecked = isChecked;
}
public T Item
{
get { return item; }
set
{
item = value;
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Item"));
}
}
public bool IsChecked
{
get { return isChecked; }
set
{
isChecked = value;
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("IsChecked"));
}
}
public string Order
{
get { return order; }
set
{
order = value;
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Order"));
}
}
}
}
The following line not working as intended
Owners.Add(new CheckedListItem<Owner>(new Owner() { OwnerName =
spOwnerSetting[0].ToString(), OwnerOrder = norder },
isChecked: bchecked));
OwnerOrder = norder is not showing when the Window is opened. My TextBox binding in XAML is simply <TextBox Text ="{Binding Order}"/>
I've also tried the following with no success
Owners.Add(new CheckedListItem<Owner>(new Owner() { OwnerName = spOwnerSetting[0].ToString() },
isChecked: bchecked, order: norder));
Any ideas?
Order Property in CheckedListItem is never initialized. you can add a new ctor
public CheckedListItem(T item, string nrorder, bool isChecked = false)
{
this.item = item;
this.isChecked = isChecked;
this.order = nrorder;
}
and change your adding method
Owners.Add(new CheckedListItem<Owner>(new Owner() { OwnerName = spOwnerSetting[0].ToString(), OwnerOrder = norder }, norder, isChecked: bchecked));
In my test app now is working.

Update in sql Ce in window phone 7

In project i user SQL CE, i have Table:
[Table]
public class Article : INotifyPropertyChanged, INotifyPropertyChanging
{
// Define _cid: private field, public property, and database column.
private int _aid;
[Column(DbType = "INT NOT NULL IDENTITY", IsDbGenerated = true, IsPrimaryKey = true)]
public int aid
{
get { return _aid; }
set
{
NotifyPropertyChanging("aid");
_aid = value;
NotifyPropertyChanged("aid");
}
}
// Define nameColor name: private field, public property, and database column.
private int _rid;
[Column]
public int rid
{
get { return _rid; }
set
{
NotifyPropertyChanging("rid");
_rid = value;
NotifyPropertyChanged("rid");
}
}
private string _title;
[Column]
public string title
{
get { return _title; }
set
{
NotifyPropertyChanging("title");
_title = value;
NotifyPropertyChanged("title");
}
}
private string _thumnail;
[Column]
public string thumnail
{
get { return _thumnail; }
set
{
NotifyPropertyChanging("thumnail");
_thumnail = value;
NotifyPropertyChanged("thumnail");
}
}
private string _DesScription;
[Column(DbType = "NTEXT")]
public string DesScription
{
get { return _DesScription; }
set
{
NotifyPropertyChanging("DesScription");
_DesScription = value;
NotifyPropertyChanged("DesScription");
}
}
private int _orderID;
[Column]
public int orderID
{
get { return _orderID; }
set
{
NotifyPropertyChanging("orderID");
_orderID = value;
NotifyPropertyChanged("orderID");
}
}
private string _pubDate;
[Column]
public string pubDate
{
get { return _pubDate; }
set
{
NotifyPropertyChanging("pubDate");
_pubDate = value;
NotifyPropertyChanged("pubDate");
}
}
private string _linkURL;
[Column]
public string linkURL
{
get { return _linkURL; }
set
{
NotifyPropertyChanging("linkURL");
_linkURL = value;
NotifyPropertyChanged("linkURL");
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
// Used to notify that a property changed
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
#region INotifyPropertyChanging Members
public event PropertyChangingEventHandler PropertyChanging;
// Used to notify that a property is about to change
private void NotifyPropertyChanging(string propertyName)
{
if (PropertyChanging != null)
{
PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
}
}
#endregion
}
when i Update Colum Thumnail , i have erros :
SQL Server does not handle comparison of NText, Text, Xml, or Image data types
because of special characters into database insert sequence trogn should I use BbType = "NTEXT"
Please Help me !
You could remove this column for concurrency checking by adding [Column(UpdateCheck = UpdateCheck.Never)] to this column.
See this blogpost about Linq to sql concurrency checking: http://blogs.msdn.com/b/matt/archive/2008/05/22/into-to-linq-to-sql-optimistic-concurrency.aspx

Categories

Resources