Below is the class file
public class BillDetails
{
private string chargecategory;
[XmlAttribute("ChargeCategory")]
public string ChargeCategory
{
get { return chargecategory; }
set { chargecategory = value; }
}
private string customername;
[XmlAttribute("CustomerName")]
public string CustomerName
{
get { return customername; }
set { customername = value; }
}
private List<Details> details;
[XmlArray("Details")]
[XmlArrayItem("details")]
// public List<Details> details = new List<Details>();
public List<Details> Details
{
get { return details; }
set { details = value; }
}
now in my code I need to databind only the properties which belong to List
List<BillDetails> billlist = new List<BillDetails>();
public int x;
List<Details> newdetails = new List<Details>();
public void Button1_Click(object sender, EventArgs e)
{
if (IsValidPost())
{
if (Session["BillList"] == null)
{
newdetails.Add(new Details() { ChargeCode = ChargeCode.Text, MaterialCode = MaterialCode.Text, GLAccount = GLAccount.Text, CostCenter = CostCenter.Text, Price = Convert.ToDecimal(Price.Text), Quantity = Convert.ToInt32(Quantity.Text), UOM = UOM.Text, Total = Convert.ToDecimal(Price.Text) * Convert.ToInt32(Quantity.Text) });
billlist.Add(new BillDetails() { ChargeCategory = ChargeCategory.Text, Details = newdetails.ToList(), CustomerName = CustomerName.Text });
GridView1.DataSource = newdetails *---works ...but if I give the datasource as billlist it does not ...but I want get down to newdetails from billlist.
GridView1.DataBind();
//Session["BillList"] = newdetails;
Session["BillList"] = billlist;
cleartextboxes();
serializetoxml(billlist);
}
how do i achieve this...also in the ascx file how do I databind the columns to the properties which are in details
I would assume DataMember = "Details"; would do this (but I don't personally use webforms data-binding, so my apologies if this fails).
Related
I have a binding source creditUserBindingSource in my below class which recieves a list of CreditUser class as datasource. In my DataGridView I have a DataGridViewComboBoxColumn called ResponsibleList which receives a list of string as DataSource ["Production", "Distribution", "Customer Service", "Sales"]. I want the ResponsibleList to display the responsible from the responsible variable from the list of CrteditUsers for each user.
public partial class CreditUserLimitsForm : Form
{
private List<CreditUser> creditUser;
private bool SetupCheckStatus = false;
//private Dictionary<string, string> fbu;
public CreditUserLimitsForm()
{
InitializeComponent();
}
private void CreditUserLimitsForm_Load(object sender, EventArgs e)
{
//fbu = MainForm.srv.GetFBU();
//foreach (KeyValuePair<string, string> k in fbu)
//{
// lvwFBU.Items.Add(new ListViewItem(new string[] { k.Key, k.Value }));
//}
try
{
creditUser = MainForm.srv.GetCreditUser("","").ToList();
creditUserBindingSource.DataSource = creditUser;
SetAlternateChoicesUsingDataSource(ResponsibleList);
}
catch (Exception ex)
{
Cursor = Cursors.Default;
NutraMsg.DisplayError(this, ex, MainForm.GetMessageDisplayType());
}
}
private void SetAlternateChoicesUsingDataSource(DataGridViewComboBoxColumn comboboxColumn)
{
{
comboboxColumn.DataSource = MainForm.srv.GetResponsibleList();
comboboxColumn.ValueMember = "Responsible";
comboboxColumn.DisplayMember = comboboxColumn.ValueMember;
}
}
}
Here's the code for CreditUser class
public class CreditUser : INotifyPropertyChanged
{
public string Responsible { get; set; }
public int UserId { get; set; }
public int RoutingId { get; set; }
public string UserName { get; set; }
public List<string> AllowedCustomerTypes { get; set; }
public decimal CreditLimit { get; set; }
public bool Restricted
{
get
{
foreach (UserCatalog uc in Catalogs)
{
if (uc.Restricted)
{
return true;
}
}
return false;
}
}
}
If you're binding a list of string values then don't set the DisplayMember or ValueMember. The point of those is to specify members of the items you want to use but you don't want to use members of the items. You want to use the items themselves. Here is a simple example that demonstrates this:
private class Record
{
public int Id { get; set; }
public string Name { get; set; }
}
private void Form1_Load(object sender, EventArgs e)
{
var idColumn = new DataGridViewTextBoxColumn { HeaderText = "Id", DataPropertyName = "Id" };
var nameColumn = new DataGridViewComboBoxColumn
{
HeaderText = "Name",
DataPropertyName = "Name",
DataSource = new[] {"First", "Second", "Third"}
};
dataGridView1.Columns.AddRange(idColumn, nameColumn);
dataGridView1.DataSource = new BindingList<Record>
{
new() {Id = 1, Name = "First"},
new() {Id = 2, Name = "Second"},
new() {Id = 3, Name = "Third"}
};
}
I see that you have made a custom DataGridComboBoxColumn and have implemented a version of SetAlternateChoicesUsingDataSource that seems to be modeled after the method of the same name in the Microsoft code example for DataGridViewComboBoxColumn.
The purpose of SetAlternateChoicesUsingDataSource in that example is to provide ComboBox drop down options that are tailored and specified for each user using the AllowedCustomerTypes property that you show in your CreditUser class. Something like this:
But based on your comment, the choices are the same for each row. More like this:
This means that your code can be simplified.
DataSources for DataGridViewComboBoxColumn and DataGridView
I believe what might be causing the confusion is that the data sources for DataGridView and for DataGridViewComboBoxColumn are completely unrelated in this case. Since there is no need to provide each user with individualized options, the source of drop down items only needs to be set one time for the entire column.
The DataSource for DataGridViewComboBoxColumn is an array of strings named ResponsibleList that will not change.
private readonly string[] ResponsibleList = new []
{
"Production",
"Distribution",
"Customer Service",
"Sales",
String.Empty
};
The DataSource for dataGridViewCreditUser is a binding list named CreditUsers.
readonly BindingList<CreditUser> CreditUsers = new BindingList<CreditUser>();
Initialize
Assigning these data sources is done in the override of OnLoad (there's no need to have the form subscribe to its own Load event). Allow me to explain what I've done and you can modify this flow to your specific requirements.
protected override void OnLoad(EventArgs e)
{
dataGridViewCreditUser.DataSource = CreditUsers;
Adding one or more items will autogenerate the columns.
// Calls a mock method that returns a simulated response of three CreditUsers.
foreach (var creditUser in mockMainForm_srv_GetCreditUser("", ""))
{
CreditUsers.Add(creditUser);
}
Create a ComboBox column that will be swapped out for the autogenerated one. This is where ResponsibleList becomes the DataSource for the ComboBox.
var colCB = new DataGridViewComboBoxColumn
{
Name = nameof(CreditUser.Responsible),
// Connects the column value to the Responsible property of CreditUser
DataPropertyName = nameof(CreditUser.Responsible),
AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells,
// Connects the four drop-down options in ResponsibleList to the ComboBox
DataSource = ResponsibleList,
};
Perform the swap. Remove the autogenerated column and replace it with the custom version.
var index = dataGridViewCreditUser.Columns[nameof(CreditUser.Responsible)].Index;
dataGridViewCreditUser.Columns.RemoveAt(index);
dataGridViewCreditUser.Columns.Insert(index, colCB);
Make sure the cell is NOT left in an editing state after change of ComboBox or CheckBox.
dataGridViewCreditUser.CurrentCellDirtyStateChanged += (sender, e) =>
{
switch (dataGridViewCreditUser.Columns[dataGridViewCreditUser.CurrentCell.ColumnIndex].Name)
{
case nameof(CreditUser.Responsible):
case nameof(CreditUser.Restricted):
dataGridViewCreditUser.CommitEdit(DataGridViewDataErrorContexts.Commit);
break;
}
};
To monitor ongoing changes, update the Title bar whenever the source list is modified.
CreditUsers.ListChanged += (sender, e) =>
{
if ((dataGridViewCreditUser.CurrentCell != null) && (dataGridViewCreditUser.CurrentCell.RowIndex < CreditUsers.Count))
{
var creditUser = CreditUsers[dataGridViewCreditUser.CurrentCell.RowIndex];
Text = creditUser.ToString();
}
};
Now that the DataGridView is all set up the columns can be formatted.
foreach (DataGridViewColumn col in dataGridViewCreditUser.Columns)
{
if (col.Name == nameof(CreditUser.UserName))
{
col.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
}
else
{
col.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
}
}
}
MOCK QUERY FOR TESTING
// MOCK for minimal example
private List<CreditUser> mockMainForm_srv_GetCreditUser(string v1, string v2)
{
return new List<CreditUser>
{
new CreditUser
{
UserName = "Tom",
CreditLimit=10000m,
},
new CreditUser
{
UserName = "Richard",
CreditLimit=1250m,
Restricted = true
},
new CreditUser
{
UserName = "Harry",
CreditLimit=10000m,
},
};
}
CreditUser class
// REDUCED for minimal example
public class CreditUser : INotifyPropertyChanged
{
string _UserName = string.Empty;
public string UserName
{
get => _UserName;
set
{
if (!Equals(_UserName, value))
{
_UserName = value;
OnPropertyChanged();
}
}
}
string _Responsible = String.Empty;
public string Responsible
{
get => _Responsible;
set
{
if (!Equals(_Responsible, value))
{
_Responsible = value;
OnPropertyChanged();
}
}
}
decimal _CreditLimit = 0;
public decimal CreditLimit
{
get => _CreditLimit;
set
{
if (!Equals(_CreditLimit, value))
{
_CreditLimit = value;
OnPropertyChanged();
}
}
}
bool _Restricted = false;
public bool Restricted
{
get => _Restricted;
set
{
if (!Equals(_Restricted, value))
{
_Restricted = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = null) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
public override string ToString()
{
var ctype = Responsible == string.Empty ? "Not Specified" : $"{Responsible}";
return Restricted ?
$"{UserName} ({ctype}) Restricted" :
$"{UserName} ({ctype}) {CreditLimit}";
}
}
I populate a data grid with a list of objects that come from a repository like this:
public static IEnumerable<Order> GetOrdersForDataGrid()
{
IEnumerable<Order> query;
using (RSDContext = new RSDContext())
{
query = context.Orders.Include(o=>o.OrderDetails).ToList();
}
return query;
}
When I want to edit an order I pass the selected row to a new window like this:
OrderEditWindow orderEdit = new OrderEditWindow();
orderEdit.SelectedOrder = SelectedOrder;
orderEdit.ShowDialog();
Here I set the DataContext of the Window to:
DataContext = SelectedOrder;
In this window I have another data grid that binds to OrderDetails collection property of Order. The problem is on CRUD operations on OrderDetails. For example, after I add a new orderDetail like this:
private void AddProductDetailButton_OnClick(object sender, RoutedEventArgs e)
{
if (!ValidateProductDetail())
return;
var _selectedProduct = ProductAutoCompleteBox.SelectedItem as Product;
var selectedProduct = ProductsRepository.GetProductById(_selectedProduct.ProductId);
OrderDetail orderDetail = new OrderDetail();
orderDetail.Price = selectedProduct.Price;
orderDetail.ProductCode = selectedProduct.Code;
orderDetail.ProductName = selectedProduct.Name;
orderDetail.Quantity = int.Parse(QuantityNumericUpDown.Value.ToString());
orderDetail.Um = selectedProduct.Um;
orderDetail.Total = selectedProduct.Price * int.Parse(QuantityNumericUpDown.Value.ToString());
orderDetail.Group = selectedProduct.Subgroup.Group.Name;
orderDetail.Subgroup = selectedProduct.Subgroup.Name;
orderDetail.SupplierName = selectedProduct.Supplier.Name;
//orderDetail.Order=SelectedOrder;
//orderDetail.OrderId = SelectedOrder.OrderId;
SelectedOrder.OrderDetails.Add(orderDetail);
ProductAutoCompleteBox.Text = string.Empty;
QuantityNumericUpDown.Value = 1;
ProductAutoCompleteBox.Focus();
}
and then I call the update method from repository:
public static void UpdateOrder(Order order)
{
using (RSDContext context = new RSDContext())
{
context.Orders.Attach(order);
context.Entry(order).State = EntityState.Modified;
context.SaveChanges();
}
}
I get an error about OrderId. If i set manualy the navigation property and the id I don't get an error but changes dont get saved into db.
My Order model look like this:
public class Order : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public Order()
{
_OrderDetails = new ObservableCollection<OrderDetail>();
_OrderDetails.CollectionChanged += _OrderDetails_CollectionChanged;
}
void _OrderDetails_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
AttachProductChangedEventHandler(e.NewItems.Cast<OrderDetail>());
if (e.OldItems != null)
CalcualteTotals();
}
[NotMapped]
public decimal CalculatedTotal
{
get
{
return OrderDetails.Sum(x => x.Total);
}
}
public int OrderId { get; set; }
private int _Number;
public int Number
{
get { return _Number; }
set
{
_Number = value;
NotifyPropertyChanged("Number");
}
}
private DateTime _Date;
public DateTime Date
{
get { return _Date; }
set
{
_Date = value;
NotifyPropertyChanged("Date");
}
}
private bool _Canceled;
public bool Canceled
{
get { return _Canceled; }
set
{
_Canceled = value;
NotifyPropertyChanged("Canceled");
}
}
private string _ClientName;
public string ClientName
{
get { return _ClientName; }
set
{
_ClientName = value;
NotifyPropertyChanged("ClientName");
}
}
private string _ClientPhone;
public string ClientPhone
{
get { return _ClientPhone; }
set
{
_ClientPhone = value;
NotifyPropertyChanged("ClientPhone");
}
}
private string _DeliveryAddress;
public string DeliveryAddress
{
get { return _DeliveryAddress; }
set
{
_DeliveryAddress = value;
NotifyPropertyChanged("DeliveryAddress");
}
}
private decimal _Transport;
public decimal Transport
{
get { return _Transport; }
set
{
_Transport = value;
NotifyPropertyChanged("Transport");
}
}
private decimal _Total;
public decimal Total
{
get { return _Total; }
set
{
_Total = value;
NotifyPropertyChanged("Total");
}
}
private ObservableCollection<OrderDetail> _OrderDetails;
public virtual ObservableCollection<OrderDetail> OrderDetails
{
//get { return _OrderDetails ?? (_OrderDetails = new ObservableCollection<OrderDetail>()); }
get
{
return _OrderDetails;
}
set
{
_OrderDetails = value;
NotifyPropertyChanged("OrderDetails");
}
}
private void AttachProductChangedEventHandler(IEnumerable<OrderDetail> orderDetails)
{
foreach (var p in orderDetails)
{
p.PropertyChanged += (sender, e) =>
{
switch (e.PropertyName)
{
case "Quantity":
case "Price":
case "Total":
CalcualteTotals();
break;
}
};
}
CalcualteTotals();
}
public void CalcualteTotals()
{
NotifyPropertyChanged("CalculatedTotal");
}
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
}
}
}
And my OrderDetail model look like this:
public class OrderDetail : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public int OrderDetailId { get; set; }
public int OrderId { get; set; }
public Order Order { get; set; }
private int _ProductCode;
public int ProductCode
{
get { return _ProductCode; }
set
{
_ProductCode = value;
NotifyPropertyChanged("ProductCode");
}
}
private string _ProductName;
public string ProductName
{
get { return _ProductName; }
set
{
_ProductName = value;
NotifyPropertyChanged("ProductName");
}
}
private string _Um;
public string Um
{
get { return _Um; }
set
{
_Um = value;
NotifyPropertyChanged("Um");
}
}
private decimal _Price;
public decimal Price
{
get { return _Price; }
set
{
_Price = value;
NotifyPropertyChanged("Price");
NotifyPropertyChanged("Total");
}
}
private int _Quantity;
public int Quantity
{
get { return _Quantity; }
set
{
_Quantity = value;
NotifyPropertyChanged("Quantity");
NotifyPropertyChanged("Total");
}
}
private string _SupplierName;
public string SupplierName
{
get { return _SupplierName; }
set
{
_SupplierName = value;
NotifyPropertyChanged("SupplierName");
}
}
private string _Subgroup;
public string Subgroup
{
get { return _Subgroup; }
set
{
_Subgroup = value;
NotifyPropertyChanged("Subgroup");
}
}
private string _Group;
public string Group
{
get { return _Group; }
set
{
_Group = value;
NotifyPropertyChanged("Group");
}
}
public decimal _Total;
public decimal Total
{
get { return Quantity * Price; }
set
{
_Total = value;
NotifyPropertyChanged("Total");
}
}
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
}
}
}
I'm really trying to use some sort of unit of work and I don't understand how i'm supposed to apply CRUD on objects with child collections and keep the UI updated in the same time (by working in a ObservableCollection and using Binding ClientPhone, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged my parent window is updated as I type)
A final working solution:
using (RSDContext context = new RSDContext())
{
var details = order.OrderDetails;
order.OrderDetails = null;
List<int> OriginalOrderDetailsIds =
context.OrderDetails.Where(o => o.OrderId == order.OrderId).Select(o => o.OrderDetailId).ToList();
List<int> CurrentOrderDetailsIds = details.Select(o => o.OrderDetailId).ToList();
List<int> DeletedOrderDetailsIds = OriginalOrderDetailsIds.Except(CurrentOrderDetailsIds).ToList();
context.Entry(order).State = EntityState.Modified;
foreach (var deletedOrderDetailId in DeletedOrderDetailsIds)
{
context.Entry(context.OrderDetails.Single(o => o.OrderDetailId == deletedOrderDetailId)).State = EntityState.Deleted;
}
foreach (OrderDetail detail in details)
{
// Add.
if (detail.OrderDetailId == 0)
{
detail.OrderId = order.OrderId;
context.Entry(detail).State = EntityState.Added;
}
// Update.
else
{
context.Entry(detail).State = EntityState.Modified;
}
}
context.SaveChanges();
}
You could do this way for adding and updating the child, but not sure about deleted order details in the ui. If you don't want to get the order from entity, you need some kind of marking in the OrderDetail for deleted OrderDetail.
using (RSDContext context = new RSDContext())
{
var details = order.OrderDetails;
order.OrderDetails = null;
context.Entry(order).State = EntityState.Modified;
foreach (var detail in details)
{
if (detail.Id == 0)
{
// Adds.
detail.OrderId = order.Id;
context.Entry(detail).State = EntityState.Added;
}
else if (detail.IsDeleted)
// Adds new property called 'IsDeleted'
// and add [NotMapped] attribute
// then mark this property as true from the UI for deleted items.
{
// Deletes.
context.Entry(detail).State = EntityState.Deleted;
}
else
{
// Updates.
context.Entry(detail).State = EntityState.Modified;
}
}
order.OrderDetails = details;
context.SaveChanges();
}
SOLVED
THANKS TO HAR07 FOR HELPING ME OUT AND ANYONE THAT ELSE HAS COMMENTED!
public partial class xamlAuditorDashboard : Window
{
cEvolve_SP sp = new cEvolve_SP(Properties.Settings.Default.AppConnectionString);
List<cAuditTasksEntity> _tasks;
cAuditUserEntity _loggedInUser;
public xamlAuditorDashboard(cAuditUserEntity loggedInUser)
{
_loggedInUser = loggedInUser;
InitializeComponent();
_tasks = new List<cAuditTasksEntity>();
Refresh();
}
private void Refresh()
{
var _AuditUserId = _loggedInUser;
cAuditUserEntity user = _AuditUserId as cAuditUserEntity;
int userid = user.AuditUserId;
_tasks = sp.GetTasksByUser(userid).ToList();
var result = (from cAuditTasksEntity tasks in _tasks
select tasks.TaskId).ToList();
cmbToDoList.ItemsSource = result;
}
private void btnAudit_Click(object sender, RoutedEventArgs e)
{
var Audit = cmbToDoList.SelectedItem;
var _TransactionId = Audit;
cAuditTransactionsEntity transaction = _TransactionId as cAuditTransactionsEntity;
string transactionid = transaction.TransactionId;
sp.GetTransactionInfo(transactionid);
}
What I am trying to do is, from having a TaskId I want to find out the TransactionId.
From my code in my Refresh method I getting the LoggedOnUser and searching the TaskTable for it then to bring out any tasks that there ID is next to, then to display the `TaskIds' in a combobox on there page.
What i am looking to do is when they click on the TaskId in the combobox and click New Audit, another page will load up and display all different information.
http://i.stack.imgur.com/Bgek2.png
This is the TaskTable, the TaskID is what shows up in there combobox.
When they select a new ID from there combobox and click next, I need it to find the transactionId next to the TaskId they clicked, then bring back:
http://i.stack.imgur.com/APp6E.png
all the information in the circle?
EDIT:
The cAuditTasksEntity:
namespace DAL
{
[Table(Name = "Audit_Tasks")]
public class cAuditTasksEntity
{
private int _TaskId;
private int _AuditUserId;
private string _TransactionId;
private string _TaskTypeId;
private DateTime _Date;
private string _AuditStatus;
[Column(DbType = "INT", IsPrimaryKey = true, IsDbGenerated = true)]
public int TaskId
{
get { return _TaskId; }
set { _TaskId = value; }
}
[Column(DbType = "INT")]
public int AuditUserId
{
get { return _AuditUserId; }
set { _AuditUserId = value; }
}
[Column(DbType = "CHAR(32)")]
public string TransactionId
{
get { return _TransactionId; }
set { _TransactionId = value; }
}
[Column(DbType = "CHAR(32)")]
public string TaskTypeId
{
get { return _TaskTypeId; }
set { _TaskTypeId = value; }
}
[Column(DbType = "DATETIME")]
public DateTime Date
{
get { return _Date; }
set { _Date = value; }
}
[Column(DbType = "VARCHAR(255)")]
public string AuditStatus
{
get { return _AuditStatus; }
set { _AuditStatus = value; }
}
}
}
Also the properties i see are these 4 :
ToString();
GetHashCode();
GetType();
Equals();
EDIT2:
This is what Audit.GetType(); is showing but I don't understand?
I added this code:
var result = Audit.GetType();
and then this set result to be equal to:
{Name = "Int32" FullName = "System.Int32"
I think this is what you are looking for, getting transactionId given TaskId:
var _TransactionId = (from task transactionid in _tasks
where task.TaskId == (int)cmbToDoList.SelectedItem
select task.TransactionId).FirstOrDefault();
I want to load values from database in user control
I could add more user control but I cant't able to load values in user control
Code:
Add.aspx.cs
Below code is for adding more than one user control and retain the previous control values
public List<string> NoOfControls
{
get
{
return ViewState["NoOfControls"] == null ? new List<string>() : (List<string>)ViewState["NoOfControls"];
}
set
{
ViewState["NoOfControls"] = value;
}
}
protected override void LoadViewState(object savedState)
{
base.LoadViewState(savedState);
GenerateControls();
}
private void GenerateControls()
{
foreach (string i in NoOfControls)
{
VisaUserControl ctrl = (VisaUserControl)Page.LoadControl("VisaUserControl.ascx");
ctrl.ID = i;
this.rpt1.Controls.Add(ctrl);
}
}
protected void btnAddVisa_Click(object sender, EventArgs e)
{
List<string> temp = null;
var uc = (VisaUserControl)this.LoadControl(#"VisaUserControl.ascx");
string id = Guid.NewGuid().ToString();
uc.ID = id;
temp = NoOfControls;
temp.Add(id);
NoOfControls = temp;
rpt1.Controls.Add(uc);
}
Edit.aspx.cs
Below code is for loading values from database in user control
using (OleDbCommand cmd = new OleDbCommand("Select * from visa_details where emp_id = '"+ empid +"'", DbConnection))
using (OleDbDataAdapter da = new OleDbDataAdapter(cmd))
{
OleDbDataReader DR1 = cmd.ExecuteReader();
while(DR1.Read())
{
//Here I can get values
string visaNumb = DR1[2].ToString();
string visaCountry = DR1[3].ToString();
string visaType = DR1[4].ToString();
string visaEntry = DR1[5].ToString();
string expiryDate = DR1[6].ToString();
for (int i = 0; i < y; i++)
{
VisaUserControl userconrol = (VisaUserControl)Page.LoadControl("VisaUserControl.ascx");
userconrol.TextVisaNumber = visaNumb;
userconrol.VisaCountry = visaCountry;
userconrol.VisaType = visaType;
userconrol.VisaEntry = visaEntry;
userconrol.ExpiryDate = expiryDate;
repeater1.Controls.Add(userconrol);
}
}
}
.ascx.cs
Here values are there but when it is loading all values are removed
protected void Page_Load(object sender, EventArgs e)
{
txtUser.Text = Request.Form[txtUser.UniqueID];
dropCountry.SelectedValue = Request.Form[dropCountry.UniqueID];
dropVisa.SelectedValue = Request.Form[dropVisa.UniqueID];
dropEntry.SelectedValue = Request.Form[dropEntry.UniqueID];
txtDate.Text = Request.Form[txtDate.UniqueID];
}
public string TextVisaNumber
{
get { return txtUser.Text; }
set { txtUser.Text = value; }
}
public string VisaCountry
{
get { return dropCountry.SelectedValue; }
set { dropCountry.SelectedValue = value; }
}
public string VisaType
{
get { return dropVisa.SelectedValue; }
set { dropVisa.SelectedValue = value; }
}
public string VisaEntry
{
get { return dropEntry.SelectedValue; }
set { dropEntry.SelectedValue = value; }
}
public string ExpiryDate
{
get
{
return txtDate.Text;
}
set
{
txtDate.Text = value;
}
}
Any ideas? Thanks in advance
Instead of adding the control in the page's controls collection, you should keep an set the data in some existing control's inner HTML.
I have a custom dataset style class defined as:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
namespace LibrarySort.Data
{
public class LibraryData
{
private AlbumList albums;
public AlbumList Albums { get { return albums; } }
public LibraryData()
{
this.albums = new AlbumList();
this.albums.AllowEdit = true;
this.Albums.AllowNew = true;
this.Albums.AllowRemove = true;
}
public void FillAll()
{
this.Albums.Fill();
}
}
public class AlbumList : BindingList<Album>
{
public AlbumList()
{
}
public void Fill()
{
int id = 1;
Album album1 = new Album();
album1.Id = id++;
album1.Artist = "Classical Piano Artist";
album1.Download = true;
album1.Person = null;
album1.Price = (decimal?)3.49;
album1.Tags.Add("classical");
album1.Tags.Add("piano");
album1.Title = "Classical Piano";
Album album2 = new Album();
album2.Id = id++;
album2.Artist = "Thrash Metal Artist";
album2.Download = false;
album2.Person = null;
album2.Price = (decimal?)7.99;
album2.Tags.Add("thrash metal");
album2.Title = "Thrash Metal";
this.Items.Add(album1);
this.Items.Add(album2);
}
}
}
I also a have Form object that inside a TabControl has a DataGridView. In the designer, I created a BindingSource and used the Add Project Data Source to create a source from the top level LibraryData object. I then bind the DataGridView to the "Albums" data member, all in the designer, and the columns get populated in the designer as expected.
When running the code, the table isn't populated, which makes sense as the Fill() hasn't been run. So I create a Load event handler for the form as follows:
private void MainForm_Load(object sender, EventArgs e)
{
LibraryData data = (LibraryData)bindingSource.DataSource;
data.FillAll();
}
However on run I get the following in MainForm_Load():
System.InvalidCastException was unhandled
Message="Unable to cast object of type 'System.RuntimeType' to type 'LibrarySort.Data.LibraryData'
I've Googled extensively on this, and in StackOverflow but no luck. Am I missing something?
Update: DataSource is definitely non-null. Also interestingly, in the designer code I see this:
this.bindingSource.DataSource = typeof(LibrarySort.Data.LibraryData);
Update 2: Album class and parent Item:
namespace LibrarySort.Data
{
public class Album : Item
{
bool download = false;
public bool Download { get { return download; } set { download = value; } }
string artist = null;
public string Artist { get { return artist; } set { artist = value; } }
}
}
namespace LibrarySort.Data
{
public class Item
{
int id = -1;
public int Id { get { return id; } set { id = value; } }
// FK to Person that currently has possession of item
int? person = null;
public int? Person { get { return person; } set { person = value; } }
string title = null;
public string Title { get { return title; } set { title = value; } }
decimal? price = null;
public decimal? Price { get { return price; } set { price = value; } }
State state = State.Owned;
public State State { get { return state; } set { state = value; } }
List<string> tags = null;
public List<string> Tags
{
get
{
if (tags == null)
tags = new List<string>();
return tags;
}
// No set needed
}
}
}
I think the issue is that although you have a binding source on your form, you have not set the datasource of the binding source.
Assuming that bindingSource is the datasource you dropped on your form, then try the following in the MainForm_Load:
LibraryData data = new LibraryData();
data.FillAll();
bindingSource.DataSource = data;