C# Changing other values on everytime something is changed using mvvm - c#

I have a DataGrid that is bound to an ObservableCollection<Item>. When I change the Quantity of an Item I would like to automatically change the total of the item. Which is Quantity*Cost=Total
<DataGrid ItemsSource="{Binding Invoices.Items}" AutoGenerateColumns="False">
<DataGridTextColumn Header="Name" Binding="{Binding Name}" />
<DataGridTextColumn Header="Quantity" Binding="{Binding Quantity}" />
<DataGridTextColumn Header="Cost" Binding="{Binding Cost}" />
<DataGridTextColumn Header="Total" Binding="{Binding Total}" />
</DataGrid>
The ViewModel is vary simple"
public class ViewModel:BaseClass
{
public ViewModel()
{
FillInvoice();
}
private Invoice _invoice;
public Invoice Invoice
{
get { return _invoice; }
set
{
if (_invoice!=value)
{
_invoices = value;
OnPropertyChanged();
}
}
}
private void FillInvoice()
{
var customer = new Customer() {Id=1,Name = "James"};
var invoice = new Invoice() {Customer = customer, Id = 1,CustomerId = 1};
var item = new Item() {Cost = Convert.ToDecimal(12.50),Id = 1,Name = "Item"};
for (int i = 0; i < 10; i++)
{
invoice.Items.Add(item);
}
Invoices = invoice;
}
}
The Invoice Look like:
public Invoices()
{
Items=new ObservableCollection<Item>();
}
public int Id { get; set; }
public int CustomerId { get; set; }
public Customer Customer { get; set; }
public ObservableCollection<Item> Items { get; set; }
My Item Looks like:
public class Item:BaseClass
{
private string _name;
private decimal _cost;
public int Id { get; set; }
public string Name
{
get { return _name; }
set
{
if (_name!=value)
{
_name = value;
OnPropertyChanged();
}
}
}
private int _quantity;
public int Quantity
{
get { return _quantity; }
set
{
if (_quantity!=value)
{
_quantity = value;
OnPropertyChanged();
}
}
}
public decimal Cost
{
get { return _cost; }
set
{
if (_cost!=value)
{
_cost = value;
OnPropertyChanged();
}
}
}
private decimal _total;
public decimal Total
{
get { return _total; }
set
{
if (_total != value)
{
_total = value;
OnPropertyChanged();
}
}
}
}
What I was thinking was adding an eventhandler to the Quantity item that will calculate the total for me but I am not sure how to do that I have Tried adding.
public ViewModel(){
Invoice.Items.Quantity.PropertyChanged += (s,e)
{
Total = Cost*Quantity
}
}
public Item()
{
Quantity.PropertyChanged += (s,e)
{
Total = Cost*Quantity
}
}
but it doesn't compile on them.

You could just implement Total as a calculated property, if it is always equal to Cost*Quantity, as there is no point in storing redundant data :
public decimal Total
{
get { return Cost * Quantity; }
}
This should then just work, assuming OnPropertyChanged() with no parameters fires a generic/null property change event which will cause all subscribed properties to be rechecked.

Try adding OnPropertyChanged("Total"); to your Quantity property:
private int _quantity;
public int Quantity
{
get { return _quantity; }
set
{
if (_quantity!=value)
{
_quantity = value;
OnPropertyChanged();
Total = Cost*Quantity
OnPropertyChanged("Total");
}
}
}

You could have the code written within your Property like so:
private decimal _total;
private int _quantity;
private decimal _cost
public decimal Quantity
{
get { return _quantity; }
set
{
_quantity = value;
Total = _quantity * _cost;
}
}
public decimal Total
{
get { return _total; }
set
{
if (_total != value)
{
_total = value;
OnPropertyChanged();
}
}
}

Related

Telerik datagrid Refresh data: Button in view is working but event not

I struggle to refresh the data attached to the RADdatagrid. The view with the Datagrid shows the position of a team in a competition. Every time a new game is finished the view has to be updated automatically. The data is stored in a sqlite database and a simple sql query gets the positions from the database. A button in the view that calls the query method does the job but I want to update the grid directly after the finished game is stored. I implemented INotifyPropertyChanged but no result. I also tried to fire the button_click event but that also didn't bring me the result. I want to do this right but I am open to a quick and dirty solution. Here is a bit of my code:
<StackPanel Grid.Row="2" Orientation="Horizontal">
<TextBlock Grid.Row="2" Margin="40,0,0,5">Team Ranking</TextBlock>
<Button x:Name="RefreshViewButton" Command="{Binding Path=RefreshView}" Margin="40 0 0 0 " Click="RefreshViewButton_Click">Refresh</Button>
</StackPanel>
<StackPanel Grid.Row="6" Margin="0, 0, 50, 0" VerticalAlignment="Stretch">
<telerikGrid:RadDataGrid
AutoGenerateColumns="False"
x:Name="Datagrid"
BorderThickness="0"
ItemsSource="{x:Bind ViewModel.TeamResult, Mode=TwoWay}"
ColumnDataOperationsMode="Flyout"
GridLinesVisibility="None"
RelativePanel.AlignLeftWithPanel="True"
RelativePanel.AlignRightWithPanel="True"
UserEditMode="None" >
<telerikGrid:RadDataGrid.Columns>
<telerikGrid:DataGridNumericalColumn PropertyName="Rank" Header="Rank" SizeMode="Auto"/>
<telerikGrid:DataGridTextColumn PropertyName="Team_Naam" Header="TeamNaam" SizeMode="Auto"/>
<telerikGrid:DataGridTextColumn PropertyName="WedstrijdPunten" Header="WP" CanUserEdit="False" CanUserFilter="False" CanUserGroup="False" CanUserReorder="False" CanUserResize="False" CanUserSort="False" SizeMode="Auto" />
<telerikGrid:DataGridTextColumn PropertyName="PuntenVoor" Header="GP" SizeMode="Auto"/>
</telerikGrid:RadDataGrid.Columns>
</telerikGrid:RadDataGrid>
</StackPanel>
This is my view:
public sealed partial class TeamTotals : Page
{
public TeamResultsViewModel ViewModel { get; set; } = new TeamResultsViewModel();
public TeamTotals()
{
DataContext = ViewModel;
this.InitializeComponent();
}
public void RefreshViewButton_Click(object sender, RoutedEventArgs e)
{
ViewModel.LoadTeamResultsData();
}
}
My ViewModel:
public class TeamResultsViewModel : TeamModel
{
//public List<TeamModel> TeamResult = new List<TeamModel>();
public ObservableCollection<TeamModel> TeamResult = new ObservableCollection<TeamModel>();
TeamModel tm = new TeamModel();
public TeamResultsViewModel()
{
LoadTeamResultsData();
tm.PropertyChanged += Tm_PropertyChanged;
}
private void Tm_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
throw new NotImplementedException();
}
public void LoadTeamResultsData()
{
int i = 0;
if(TeamResult != null)
{
TeamResult.Clear();
}
try
{
string sql = "Select Team_Naam, WedstrijdPunten, PuntenVoor, PuntenTegen FROM Team WHERE KlasseId = 1 " +
"ORDER BY WedstrijdPunten DESC, PuntenVoor DESC LIMIT 10;";
var resultaat = SqliteDataAccess.LoadData<TeamModel>(sql, new Dictionary<string, object>());
foreach (var x in resultaat)
{
TeamResult.Add(x);
x.Rank = i++;
}
}
catch (Exception ex)
{
var messagedialog2 = new MessageDialog($"{ex}");
_ = messagedialog2.ShowAsync();
}
return;
}
}
and the model:
public class TeamModel : INotifyPropertyChanged
{
private int _id;
public int Id
{
get { return _id; }
set { _id = value; }
}
private int _klasseId;
public int KlasseId
{
get { return _klasseId; }
set { _klasseId = value; }
}
private string _team_naam;
public string Team_Naam
{
get { return _team_naam; }
set { _team_naam = value; }
}
private int _coachId;
public int CoachId
{
get { return _coachId; }
set { _coachId = value; }
}
private int _clubId;
public int ClubId
{
get { return _clubId; }
set { _clubId = value; }
}
private int _puntenVoor;
public int PuntenVoor
{
get { return _puntenVoor; }
set { _puntenVoor = value; }
}
private int _puntenTegen;
public int PuntenTegen
{
get { return _puntenTegen; }
set { _puntenTegen = value; }
}
private int _wedstrijdPunten;
public int WedstrijdPunten
{
get { return _wedstrijdPunten; }
set
{
_wedstrijdPunten = value;
OnPropertyChanged("WedstrijdPunten");
}
}
private int _rank;
public int Rank
{
get { return _rank; }
set { _rank = value; }
}
public List<SpelerModel> TeamLeden { get; set; } = new List<SpelerModel>();
public string Standen => $"{Team_Naam} : {PuntenVoor}";
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public override string ToString()
{
return Standen;
}
}

GridTemplateColumn databinding to complex properties

I have 3 model classes as follows (Vegetable, Fruit and ItemInBasket):
public class Vegetable
{
string name;
public string Name
{
get { return name; }
set { name = value; }
}
public Vegetable(string _Name)
{
this.Name = _Name;
}
}
public class Fruit
{
string name;
public string Name
{
get { return name; }
set { name = value; }
}
public Fruit(string _Name)
{
this.Name = _Name;
}
}
public class ItemInBasket
{
string name;
public string Name
{
get { return name; }
set { name = value; }
}
object fruitorvegetable;
public object FruitOrVegetable
{
get { return fruitorvegetable; }
set { fruitorvegetable = value; }
}
int quantity;
public int Quantity
{
get { return quantity; }
set { quantity = value; }
}
public ItemInBasket(string _Name, object _FruitOrVegetable, int _Quantity)
{
this.Name = _Name;
this.FruitOrVegetable = _FruitOrVegetable;
this.quantity = _Quantity;
}
}
My ViewModel is:
public class ViewModel
{
private ObservableCollection<object> _availableItems;
public ObservableCollection<object> AvailableItems
{
get { return _availableItems; }
set { _availableItems = value; }
}
private ObservableCollection<ItemInBasket> _itemsInBasket;
public ObservableCollection<ItemInBasket> ItemsInBasket
{
get { return _itemsInBasket; }
set { _itemsInBasket = value; }
}
public ViewModel()
{
_availableItems = new ObservableCollection<object>();
_itemsInBasket = new ObservableCollection<ItemInBasket>();
this.GenerateAvailableItems();
this.GenerateItemsInBasket();
}
private void GenerateAvailableItems()
{
_availableItems.Add(new Vegetable("Broccoli")); // index 0
_availableItems.Add(new Vegetable("Kale")); // index 1
_availableItems.Add(new Vegetable("Spinach")); // index 2
_availableItems.Add(new Vegetable("Carrots")); // index 3
_availableItems.Add(new Vegetable("Garlic")); // index 4
_availableItems.Add(new Fruit("Apple")); // index 5
_availableItems.Add(new Fruit("Orange")); // index 6
_availableItems.Add(new Fruit("Pear")); // index 7
_availableItems.Add(new Fruit("Cherry")); // index 8
_availableItems.Add(new Fruit("Grape")); // index 9
}
private void GenerateItemsInBasket()
{
_itemsInBasket.Add(new ItemInBasket("Apples",_availableItems[5],3));
_itemsInBasket.Add(new ItemInBasket("Kale", _availableItems[1], 10));
_itemsInBasket.Add(new ItemInBasket("Grape", _availableItems[9], 2));
_itemsInBasket.Add(new ItemInBasket("Carrots", _availableItems[3], 1));
}
}
I am trying to be able to modify the FruitOrVegetable inside of each ItemInBasket displayed in the datagrid but I have an issue with the data binding. I am using Syncfusion datagrid but I think it shouldnt affect anything.
<syncfusion:SfDataGrid AutoGenerateColumns="False" SelectionMode="Single"
AllowEditing="True" AllowDeleting="True" ItemsSource="{Binding ItemsInBasket,Source={StaticResource viewModel}}">
<syncfusion:SfDataGrid.Columns>
<syncfusion:GridTemplateColumn MappingName="FruitOrVegetable" HeaderText="Order">
<syncfusion:GridTemplateColumn.EditTemplate>
<DataTemplate>
<ComboBox IsEditable="True" DisplayMemberPath="Name" SelectedValuePath="Name"
Text="{Binding FruitOrVegetable.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding AvailableItems, Source={StaticResource viewModel}}"/>
</DataTemplate>
</syncfusion:GridTemplateColumn.EditTemplate>
<syncfusion:GridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</syncfusion:GridTemplateColumn.CellTemplate>
</syncfusion:GridTemplateColumn>
<syncfusion:GridNumericColumn HeaderText="Quantity" MappingName ="Quantity"/>
</syncfusion:SfDataGrid.Columns>
</syncfusion:SfDataGrid>
Your requirement to display the modified value of the FruitOrVegetable in SfDataGrid can be achieved by binding the SelectedValue property of ComboBox. Please refer to the below code snippet,
<ComboBox IsEditable="True" DisplayMemberPath="Name" SelectedValuePath="Name"
SelectedValue="{Binding Name}"
Text="{Binding FruitOrVegetable.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding AvailableItems, Source={StaticResource viewModel}}"/>
This is where what we call an "interface" comes in handy. This gives you the surety that the properties are indeed present on this object. Consider it a contract between the class and interface to always include some properties.
You can learn more about it here
You can define an interface like this
public interface INamedItem
{
string Name {get;set;}
}
Now instead of the object type use this interface(first implement them in your vegetable and fruit class) so that you can easily bind to it(and many other benefits)
public class Vegetable : INamedItem
{
string name;
public string Name
{
get { return name; }
set { name = value; }
}
public Vegetable(string _Name)
{
this.Name = _Name;
}
}
public class Fruit: INamedItem
{
string name;
public string Name
{
get { return name; }
set { name = value; }
}
public Fruit(string _Name)
{
this.Name = _Name;
}
}
public class ItemInBasket
{
string name;
public string Name
{
get { return name; }
set { name = value; }
}
INamedItem fruitorvegetable;
public object FruitOrVegetable
{
get { return fruitorvegetable; }
set { fruitorvegetable = value; }
}
int quantity;
public int Quantity
{
get { return quantity; }
set { quantity = value; }
}
public ItemInBasket(string _Name, INamedItem _FruitOrVegetable, int _Quantity)
{
this.Name = _Name;
this.FruitOrVegetable = _FruitOrVegetable;
this.quantity = _Quantity;
}
}
For your available items it becomes:
private ObservableCollection<INamedItem> _availableItems;
public ObservableCollection<INamedItem> AvailableItems
{
get { return _availableItems; }
set { _availableItems = value; }
}
Now add normally as you have in your code so no more changes to that and check if it works :)

How do I set a different data source for the DataGridView using BindSource?

I am making an inventory project, users can pick the category, put price, quantity, etc. but with customized exceptions. I'm trying to put all of these data into the DataGridView. I've checked and supposedly I should Declare the variable showProductList of BindSourceclass inside frmAddProduct. Instantiate the BindingSource class inside the constructor of frmAddProduct().
But how exactly?
(The error comes from showProductList, I think I am missing something, but I don't know what.)
this is what I have tried:
public partial class frmAddProduct : Form
{
private string _ProductName, _Category, _MfgDate, _ExpDate, _Description;
private int _Quantity;
private double _SellPrice;
public string Product_Name (string name)
{
if (!Regex.IsMatch(name, #"^[a-zA-Z]+$"))
try
{
}
catch (Exception StringFormattException)
{
}
finally
{
}
return name;
}
public int Quantity(string qty)
{
if (!Regex.IsMatch(qty, #"^[0-9]"))
try
{
}
catch (Exception NumberFormattException)
{
}
finally
{
}
return Convert.ToInt32(qty);
}
public double SellingPrice(string price)
{
if (!Regex.IsMatch(price.ToString(), #"^(\d*\.)?\d+$"))
try
{
}
catch (Exception CurrencyFormatException)
{
}
finally
{
}
return Convert.ToDouble(price);
}
public frmAddProduct()
{
InitializeComponent();
var showProductList = new BindingSource();
}
private void frmAddProduct_Load(object sender, EventArgs e)
{
string[] ListOfProductCategory = { "Beverages", "Bread/Bakery", "Canned/Jarred Goods", "Dairy", "Frozen Goods", "Meat", "Personal Care", "Other" };
foreach(string LPC in ListOfProductCategory)
{
cbCategory.Items.Add(LPC);
}
}
private void btnAddProduct_Click(object sender, EventArgs e)
{
_ProductName = Product_Name(txtProductName.Text);
_Category = cbCategory.Text;
_MfgDate = dtPickerMfgDate.Value.ToString("yyyy-MM-dd");
_ExpDate = dtPickerExpDate.Value.ToString("yyyy-MM-dd");
_Description = richtxtDescription.Text;
_Quantity = Quantity(txtQuantity.Text);
_SellPrice = SellingPrice(txtSellPrice.Text);
showProductList.Add(new ProductClass(_ProductName, _Category, _MfgDate, _ExpDate, _SellPrice, _Quantity, _Description));
gridViewProductList.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
gridViewProductList.DataSource = showProductList;
}
}
this is the other class:
class ProductClass
{
private int _Quantity;
private double _SellingPrice;
private string _ProductName, _Category, _ManufacturingDate, _ExpirationDate, _Description;
public ProductClass(string ProductName, string Category, string MfgDate, string ExpDate, double Price, int Quantity, string Description)
{
this._Quantity = Quantity;
this._SellingPrice = Price;
this._ProductName = ProductName;
this._Category = Category;
this._ManufacturingDate = MfgDate;
this._ExpirationDate = ExpDate;
this._Description = Description;
}
public string productName
{
get
{
return this._ProductName;
}
set
{
this._ProductName = value;
}
}
public string Category
{
get
{
return this._Category;
}
set
{
this._Category = value;
}
}
public string manufacturingDate
{
get
{
return this._ManufacturingDate;
}
set
{
this._ManufacturingDate = value;
}
}
public string expirationDate
{
get
{
return this._ExpirationDate;
}
set
{
this._ExpirationDate = value;
}
}
public string description
{
get
{
return this._Description;
}
set
{
this._Description = value;
}
}
public int quantity
{
get
{
return this._Quantity;
}
set
{
this._Quantity = value;
}
}
public double sellingPrice
{
get
{
return this._SellingPrice;
}
set
{
this._SellingPrice = value;
}
}
class NumberFormattException : Exception
{
public NumberFormattException(string Quantity) : base(Quantity) { }
}
class StringFormattException : Exception
{
public StringFormattException(string Product_Name) : base(Product_Name) { }
}
class CurrencyFormatException : Exception
{
public CurrencyFormatException( string SellingPrice) : base(SellingPrice) { }
}
}
This line of code is not doing what you think it is doing…
showProductList.Add(new ProductClass(_ProductName, _Category, _MfgDate, _ExpDate, _SellPrice, _Quantity, _Description));
showProductList is a BindingSource and you need to set its DataSource property.
A BindingList<ProductClass> or a List<ProductClass> or even a DataTable will work as a DataSource for the BindingSource.
With this new “list”, the code “adds” the items to this list, then simply calls the BindingSources.ResetBindings(false) to update the grid.
Example:
Add these global variables to the form…
BindingSource ProductsBS;
BindingList<ProductClass> ListOfProducts;
Update the forms constructor to initialize the binding source and set its data source….
public Form1() {
InitializeComponent();
ProductsBS = new BindingSource();
ListOfProducts = new BindingList<ProductClass>();
ProductsBS.DataSource = ListOfProducts;
gridViewProductList.DataSource = ProductsBS;
gridViewProductList.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
}
Finally, change the button click event code like…
private void btnAddProduct_Click(object sender, EventArgs e) {
_ProductName = Product_Name(txtProductName.Text);
_Category = cbCategory.Text;
_MfgDate = dtPickerMfgDate.Value.ToString("yyyy-MM-dd");
_ExpDate = dtPickerExpDate.Value.ToString("yyyy-MM-dd");
_Description = richtxtDescription.Text;
_Quantity = Quantity(txtQuantity.Text);
_SellPrice = SellingPrice(txtSellPrice.Text);
ListOfProducts.Add(new ProductClass(_ProductName, _Category, _MfgDate, _ExpDate, _SellPrice, _Quantity, _Description));
ProductsBS.ResetBindings(false);
}
I hope this makes sense.

How to bind WPF datagrid to a property in a contained ObservableCollection

I am fairly new to C# and WPF so any help will be much appreciated.
UPDATE:
I have two objects, PurchaseOrder (PO) and PurchaseOrderDetails (POD).
PO contains an ObservableCollection of POD.
I am able to get all data needed from my database.
So when the OfficeAdmin window loads , I get all Purchase Orders from the database table and display it in the PO datagrid, when a selection is made in the dgPurchaseOrder, the details of the current Purchase Order is displayed in the dgPODescription.
However i would like to display the 'PODate' property of POD in dgPurchaseOrders, I took a look at the link #Default provided in the comments but I'm still not getting the binding to work, what am I missing?
public class PurchaseOrder : INotifyPropertyChanged
{
int _id;
string _customerName;
int _customerId;
int _purchaseOrderNumber;
int _purchaseOrderDetailsId;
private ObservableCollection<Customer> _customer;
private ObservableCollection<PurchaseOrderDetails> _purchaseOrderDetails;
public ObservableCollection<Customer> Customer
{
get { return _customer; }
set
{
_customer = value;
OnPropertyChanged("Customer");
}
}
public PurchaseOrder()
{
_customerName = String.Empty;
}
public int Id
{
get { return _id; }
set
{
_id = value;
OnPropertyChanged("Id");
}
}
public string CustomerName
{
get { return _customerName; }
set
{
_customerName = value;
OnPropertyChanged("CustomerName");
}
}
public int CustomerId
{
get { return _customerId; }
set
{
_customerId = value;
OnPropertyChanged("CustomerId");
}
}
public int PurchaseOrderId
{
get { return _purchaseOrderDetailsId; }
set
{
_purchaseOrderDetailsId = value;
OnPropertyChanged("PurchaseOrderDetailsId");
}
}
public int PurchaseOrderNumber
{
get { return _purchaseOrderNumber; }
set
{
_purchaseOrderNumber = value;
OnPropertyChanged("PurchaseOrderDetailsId");
}
}
public ObservableCollection<PurchaseOrderDetails> PurchaseOrderDetails
{
get { return _purchaseOrderDetails; }
set
{
_purchaseOrderDetails = value;
OnPropertyChanged("PurchaseOrderDetails");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string property)
{
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
public class PurchaseOrderDetails : INotifyPropertyChanged
{
int _id;
int _orderNumber;
string _customerName;
int _costPrice;
int _quantity;
int _totalAmount;
int _vat;
string _date;
string _deliveryDate;
int _productId;
string _productName;
public PurchaseOrderDetails()
{
_customerName = string.Empty;
_productName = string.Empty;
}
public int Id
{
get { return _id; }
set
{
_id = value;
OnPropertyChanged("Id");
}
}
public int OrderNumber
{
get { return _orderNumber; }
set
{
_orderNumber = value;
OnPropertyChanged("Quantity");
}
}
public string CustomerName
{
get { return _customerName; }
set
{
_customerName = value;
OnPropertyChanged("CustomerName");
}
}
public string PODate
{
get { return _date; }
set
{
_date = value;
OnPropertyChanged("PODate");
}
}
public string DeliveryDate
{
get { return _deliveryDate; }
set
{
_deliveryDate = value;
OnPropertyChanged("DeliveryDate");
}
}
public int ProductId
{
get { return _productId; }
set
{
_productId = value;
OnPropertyChanged("ProductId");
}
}
public string ProductName
{
get { return _productName; }
set
{
_productName = value;
OnPropertyChanged("ProductName");
}
}
public int CostPrice
{
get { return _costPrice; }
set
{
_costPrice = value;
OnPropertyChanged("CostPrice");
}
}
public int Quantity
{
get { return _quantity; }
set
{
_quantity = value;
OnPropertyChanged("Quantity");
}
}
public int Vat
{
get { return _vat; }
set
{
_vat = value;
OnPropertyChanged("Vat");
}
}
public int TotalAmount
{
get { return _totalAmount; }
set
{
_totalAmount = value;
OnPropertyChanged("TotalAmount");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string property)
{
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
OfficeAdmin.xaml
<DataGrid x:Name="dgPurchaseOrder"
Style="{StaticResource AdminGridStyle}"
SelectionChanged="dgPurchaseOrder_SelectionChanged"
MouseUp="dgPurchaseOrder_MouseUp">
<DataGrid.Columns>
<DataGridTextColumn x:Name="dgPOCustomerName"
Header="Customer Name"
Binding="{Binding CustomerName}"
Width="1*" />
<DataGridTextColumn x:Name="PoPurchaseOrderNumber"
Header="Order Number"
Binding="{Binding PurchaseOrderNumber}"
Width="1*" />
<DataGridTemplateColumn Header="Date">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding PurchaseOrderDetails.PODate}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<DataGrid x:Name="dgPODescription"
Style="{StaticResource AdminGridStyle}"
ItemsSource="{Binding PurchaseOrderDetails}">
<DataGrid.Columns>
<DataGridTextColumn x:Name="PoProduct"
Header="Product"
Binding="{Binding ProductName}"
Width="1*" />
<DataGridTextColumn x:Name="PoQuantity"
Header="Quantity"
Binding="{Binding Quantity}"
Width="1*" />
<DataGridTextColumn x:Name="PoCostPrice"
Header="Cost Price"
Binding="{Binding CostPrice}"
Width="1*" />
<DataGridTextColumn x:Name="PoTotalAmount"
Header="Total Amount"
Binding="{Binding TotalAmount}"
Width="1*" />
<DataGridTextColumn x:Name="PoVat"
Header="Vat"
Binding="{Binding Vat}"
Width="1*" />
<DataGridTextColumn x:Name="PoDate"
Header="Date"
Binding="{Binding PODate}"
Width="1*" />
<DataGridTextColumn x:Name="DeliveryDate"
Header="Delivery Date"
Binding="{Binding DeliveryDate}"
Width="1*" />
</DataGrid.Columns>
</DataGrid>
OfficeAdmin.xaml.cs
private void Window_Loaded(object sender, RoutedEventArgs e)
{
dgPurchaseOrder.ItemsSource = vm.getAllPurchasOrders();
dgPurchaseOrder.SelectedIndex = 0;
dgPODescription.ItemsSource = vm.PurchaseOrderDetails;
}
private void dgPurchaseOrder_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var purchaseOrder = dgPurchaseOrder.SelectedItem as PurchaseOrder;
if(purchaseOrder!=null)vm.setCurrentPurchaseOrder(purchaseOrder);
dgPODescription.ItemsSource = vm.PurchaseOrderDetails;
}
vmOfficeAdmin.cs
public ObservableCollection<PurchaseOrder> PurchaseOrder { get; set; }
public ObservableCollection<Customer> PurchaseOrderCustomer { get; set;}
public ObservableCollection<PurchaseOrderDetails> PurchaseOrderDetails {get; set; }
public PurchaseOrder CurrentPurchaseOrder { get; set; }
public vmUserManagement()
{
CurrentPurchaseOrder = new PurchaseOrder();
PurchaseOrder = new ObservableCollection<PurchaseOrder>();
PurchaseOrderCustomer = new ObservableCollection<Customer>();
PurchaseOrderDetails = new ObservableCollection<PurchaseOrderDetails>();
}
public ObservableCollection<PurchaseOrder> getAllPurchasOrders()
{
PurchaseOrder = RepoDapper.getAllPurchaseOrders();
return PurchaseOrder;
}
public void setCurrentPurchaseOrder(PurchaseOrder purchaseOrder)
{
CurrentPurchaseOrder = purchaseOrder;
PurchaseOrderDetails.Clear();
CurrentPurchaseOrder.PurchaseOrderDetails = RepoDapper.getPurchaseOrderDetails(CurrentPurchaseOrder.Id);
CurrentPurchaseOrder.Customer = RepoDapper.getPurchaseOrderCustomerDetails(CurrentPurchaseOrder.CustomerId);
foreach (var b in CurrentPurchaseOrder.PurchaseOrderDetails)
{
PurchaseOrderDetails.Add(b);
}
foreach(var d in CurrentPurchaseOrder.Customer)
{
PurchaseOrderCustomer.Add(d);
}
}

Binding to nested property

I have a class as o model:
The class Flight and flightDetails are two classes defined in the proxy of the webservice:
public class FlightView
{
public FlightView()
{
FlightDetailsElement = new FlightDetails();
Flight = new Flight();
VisibleBoarding = false;
VisibleCheckIn = false;
Visibleluggage = false;
}
public Flight Flight;
public FlightDetails FlightDetailsElement;
private bool _visibleCheckIn;
public bool VisibleCheckIn
{
get { return _visibleCheckIn; }
set { _visibleCheckIn = value; }
}
private bool _visibleBoarding;
public bool VisibleBoarding
{
get { return _visibleBoarding; }
set { _visibleBoarding = value; }
}
private bool _visibleluggage;
public bool Visibleluggage
{
get { return _visibleluggage; }
set { _visibleluggage = value; }
}
private DateTime _refreshDate;
public DateTime RefreshDate
{
get { return _refreshDate; }
set { _refreshDate = value; }
}
private string _date;
public string Date
{
get { return _date; }
set { _date = value; }
}
private string _time;
public string Time
{
get { return _time; }
set { _time = value; }
}
}
in the codebehind i set the dataxontext of the grid:
SelectedFlightView.FlightDetailsElement = e.Result;
if(!(SelectedFlightView.FlightDetailsElement.IsArrival) && !string.IsNullOrEmpty(SelectedFlightView.FlightDetailsElement.BoardingGate))
SelectedFlightView.VisibleBoarding= true;
if(!(SelectedFlightView.FlightDetailsElement.IsArrival) && !string.IsNullOrEmpty(SelectedFlightView.FlightDetailsElement.CheckInArea))
SelectedFlightView.VisibleCheckIn= true;
if ((SelectedFlightView.FlightDetailsElement.IsArrival) && !string.IsNullOrEmpty(SelectedFlightView.FlightDetailsElement.LuggageDelivery))
SelectedFlightView.Visibleluggage = true;
SelectedFlightView.RefreshDate = DateTime.Now;
SelectedFlightView.Date = SelectedFlightView.RefreshDate.ToLongDateString();
SelectedFlightView.Time = SelectedFlightView.RefreshDate.ToLongTimeString();
ContentPanelDetails.DataContext = SelectedFlightView;
My problem is when i bind in the xaml:
<TextBlock Text="{Binding FlightDetailsElement.DepartureTime}"/>
I haven't the result, but when I bind
<TextBlock Text="{Binding Time}"/> i have the result.
Any ideas please??
Regards
For the binding to work, you need to use a public property. Currently, your FlightDetailsElement is a public field. To fix your problem, just declare it as a property:
public FlightDetails FlightDetailsElement { get; set; }

Categories