DataBindings in Winform-Custom Property Didn't work - c#

For compatible Null i covered Value property. But this property cannot use in DataBindings. it's not change when control's value update. I change the control to DateTimePicker,everything is fine.What's wrong with the Value property?
Test Class
class prod
{
int id;
public int Id {
get { return id; }
set { id = value; }
}
DateTime? md;
public Nullable<DateTime> Md {
get { return md; }
set { md = value; }
}
}
//Custom DateTimePicker
[Bindable(true), Browsable(true)]
public new object Value
{
get
{
if (realDate)
{
return base.Value;
}
else
{
return DBNull.Value; //If not a real date, sent DBNull to the bound field
}
}
set
{
if (Convert.IsDBNull(value))
{
realDate = false;
oldFormat = Format; //Store the Format of the datetimepicker
Format = DateTimePickerFormat.Custom;
CustomFormat = " "; //With this custom format, the datetimepicker is empty
}
else
{
realDate = true;
CustomFormat = null;
base.Value = Convert.ToDateTime(value);
}
OnValueChanged();
}
}
//Binding Code:
prod pp=new prod();
datePicker1.DataBindings.Add("Value",pp,"Md",true,DataSourceUpdateMode.OnValidation);
i found the problem----need use WriteValue for each databinding in selectitemchanged.

use DataSourceUpdateMode.OnPropertyChanged instead of DataSourceUpdateMode.OnValidation

Related

Updating Total causing infinite loop

I current have 3 telerik:RadMaskedCurrencyInput.
The first one is the principal
The First and Second are the disbursals
At the moment I have it set up such that principal = First disbursal + Second disbursal.
I'm trying to have a case such that if I update principal it updates First Disbursal and sets second disbursal to zero. So Principal = DisbursalOne and DisbursalTwo = 0
// Pv is principal
private decimal?_pv;
public decimal? Pv { get { return _pv; } set { _pv = value; OnPropertyChanged("Pv"); } }
private decimal? _disbursalOne;
public decimal? DisbursalOne
{
get
{
return _disbursalOne;
}
set
{
_disbursalOne = value;
if (_disbursalOne != null)
DisbursalTotal = _disbursalOne + DisbursalTwo;
else
{
_disbursalOne = 0;
}
OnPropertyChanged("DisbursalOne");
}
}
Disbursal Two essentially almost identical to Disbursal one so the Code is not necessary.
private decimal? _disbursalTotal;
public decimal? DisbursalTotal
{
get { return _disbursalTotal; }
set
{
_disbursalTotal = value;
if (_disbursalTotal != null) UpdateDisbursalTotal(_disbursalTotal);
else UpdateDisbursalTotal(0);
Pv = _disbursalTotal;
OnPropertyChanged("DisbursalTotal");
}
}
I apologize for the bad title.
// Updates the Total Disbursed Fields on the UI
public void UpdateDisbursalTotal(decimal? Total)
{
var cultureInfo = Thread.CurrentThread.CurrentCulture; // You can also hardcode the culture, e.g. var cultureInfo = new CultureInfo("fr-FR"), but then you lose culture-specific formatting such as decimal point (. or ,) or the position of the currency symbol (before or after)
var numberFormatInfo = (NumberFormatInfo)cultureInfo.NumberFormat.Clone();
numberFormatInfo.CurrencySymbol = "$"; // Replace with "$" or "£" or whatever you need
Double _total = (double) Total;
DisburseString = _total.ToString("C", numberFormatInfo);
}
private string _disburseString;
public string DisburseString { get { return _disburseString; } set { _disburseString = value; OnPropertyChanged("DisburseString"); } }
It's usually a good idea to format your PropertyChanged events in the following way, that way if the same value gets set, you don't notify anyone as nothing has actually changed. If things are relying on your PropertyChanged events to update each other, this should break the cycle:
private decimal? _disbursalTotal;
public decimal? DisbursalTotal
{
get { return _disbursalTotal; }
set
{
if (value != _disburseTotal) {
_disbursalTotal = value;
if (_disbursalTotal != null) UpdateDisbursalTotal(_disbursalTotal);
else UpdateDisbursalTotal(0);
Pv = _disbursalTotal;
OnPropertyChanged("DisbursalTotal");
}
}
}
Step through the code. My guess is that OnPropertyChanged event also changes a property. You can check if the property is actually changing (or just being set to the same value) before calling OnPropertyChanged.

How can I clear/prevent binding to datagrid if duplicate exists?

Here's my property that determines if I should bind the other properties or not:
public string LotNumber {
get {
return lotNumber;
}
set {
using (var db = new DDataContext()) {
lotNumber = value;
// Check for duplicates
bool isDuplicate =
db.LotInformation.Any(r => r.lot_number == lotNumber);
if (isDuplicate == true) {
ComponentsList = null;
FamiliesList = null;
ExpirationDate = null;
LotNumber = null;
lotNumber = null;
// Inform user that the lot_number already exists
errorWindow.Message =
LanguageResources.Resource.Lot_Exists_Already;
dialogService.ShowDialog(
LanguageResources.Resource.Error, errorWindow);
logger.writeErrLog(
LanguageResources.Resource.Lot_Exists_Already);
return;
} else {
lotNumber = value;
}
RaisePropertyChanged("LotNumber");
}
}
}
My problem right now is if I upload a file and if the lot number already exists in the database, the boolean returns true and an error message is thrown. However, after that,it loops again and then the boolean is set to false since now the value is null and it still binds the data afterward. How can I break out of the loop and just make it stop running/clear/prevent binding when bool is true in the case above?
I assume you have some code like this:
LotNumber = "ABC5"; // ABC5 already exists in the database - uh oh!
And then you're trying to figure everything out in the "setter". It's already too late by that point. Instead, move your logic into separate methods:
private bool LotNumberExists(string lotNumber)
{
using (var db = new DDataContext())
{
return db.LotInformation.Any(r => r.lot_number == lotNumber);
}
}
private void ClearFields()
{
ComponentsList = null;
FamiliesList = null;
ExpirationDate = null;
LotNumber = null;
}
private void InformUserOfDuplicate()
{
// Inform user that the lot_number already exists
errorWindow.Message = LanguageResources.Resource.Lot_Exists_Already;
dialogService.ShowDialog(LanguageResources.Resource.Error, errorWindow);
logger.writeErrLog(LanguageResources.Resource.Lot_Exists_Already);
}
Then check the return value of that method before setting LotNumber.
private void SomeOtherMethod()
{
string someLotNumber = "ABC5";
if (LotNumberExists(someLotNumber)
{
ClearFields();
InformUserOfDuplicate();
return;
}
LotNumber = someLotNumber;
}
Turn your setter back into a simple setter without a ton of logic wrapped up in it:
public string LotNumber
{
get { return lotNumber; }
set
{
lotNumber = value;
RaisePropertyChanged("LotNumber");
}
}

.NET bind checked property of checkbox with SqlByte datatype

This fails:
dtaAutomaticFlag.DataBindings.Add("Checked", BndSource, "AutomaticFlag");
most probably because AutomaticFlag is defined as:
public SqlByte AutomaticFlag { get; set; }
SQL Server is tinyint. The reason is that i dont only need 0 and 0 as values.
I need to be checked if the value is 1 , unchecked for ALL other values.
One thing that i thought is to create an extra property AutomaticFlagBoolean in my class and check the AutomaticFlag and bind to the new property.
This is what i tried but i get always false:
private SqlByte _automaticFlag;
public SqlByte AutomaticFlag
{
get { return _automaticFlag; }
set
{
if (_automaticFlagBoolean)
{
_automaticFlag = 1;
}
else
{
_automaticFlag = 0;
}
}
}
private bool _automaticFlagBoolean;
public bool AutomaticFlagBoolean
{
get
{
if (_automaticFlag == 1)
{
return _automaticFlagBoolean = true;
}
else
{
return _automaticFlagBoolean = false;
}
}
set { _automaticFlagBoolean = value; }
}
this is in my binding:
dtaAutomaticFlag.DataBindings.Add("Checked", BndSource, "AutomaticFlagBoolean");
The checkbox control expects a boolean value for binding.
Try using a local variable to hold the value:
private SqlByte _automaticFlag;
private bool _automaticFlagBoolean;
public SqlByte AutomaticFlag
{
get { return _automaticFlag; }
set
{
_automaticFlag = value;
_automaticFlagBoolean = (_automaticFlag != 0);
}
}
public bool AutomaticFlagBoolean
{
get
{
return _AutomaticFlagBookean;
}
set { _automaticFlagBoolean = value;
if (_automaticFlagBoolean) {
_automaticFlag = 1;
} else {
_automaticFlag = 0;
}
}
}
Then bind as so:
dtaAutomaticFlag.DataBindings.Add("Checked", BndSource, "AutomaticFlagBoolean");
Your class should also implement INotifyPropertyChanged as well but that's a little beyond the scope of your question.

Return all the fields from a class

I am attempting to cycle through the Fields in my class, place the fields of a certain type into a list and then return that list. I know I am missing some key component but I cannot figure out what I am doing wrong. This is what I have so far:
...
I need to return a list of the actual fields as pointers, not a copy of the data. Any help in getting this to work would be appreciated.
I removed the above code (you should still be able to see it in the history) because it was confusing. This is the updated code (with some extra stuff removed) that works thanks to the answer from competent_tech:
string prop1;
BaseClass prop2;
SubClass prop3;
SubClass prop4;
public List<BaseClass> GetData()
{
List<BaseClass> DataList = new List<BaseClass>();
foreach (System.Reflection.PropertyInfo thisInfo in this.GetType().GetProperties())
{
var tempPropery = thisInfo.GetValue(this, null);
if (tempPropery.GetType().IsSubclassOf(typeof(BaseClass)) || tempPropery.GetType().Equals(typeof(BaseClass)))
{
DataList.Add((BaseClass)tempPropery);
};
}
return DataList;
}
The above code will allow you to get all the properties of a specific base type from your class and return them in a list. So the above code would return prop2 - prop4.
You can accomplish this through reflection.
foreach (System.Reflection.PropertyInfo oProperty in this.GetType().GetProperties()) {
}
There are numerous ways that you can use this information once you have it or filter the properties (for example, by adding an attribute to the properties that you want to collect).
You can get more information from MSDN.
Note that this code specifically references properties, but there are equivalent methods for retrieving fields (GetFields) and all members (GetMembers).
Once you have the PropertyInfo, you can call the GetValue method:
foreach (System.Reflection.PropertyInfo oProperty in this.GetType().GetProperties()) {
Console.WriteLine(oProperty.Name + " = " + oProperty.GetValue(this, null).ToString());
}
Alternatively, if you are looking at both fields and properties:
foreach (System.Reflection.MemberInfo oMember in this.GetType().GetMembers())
{
switch (oMember.MemberType)
{
case System.Reflection.MemberTypes.Field:
var oField = (System.Reflection.FieldInfo)oMember;
Console.WriteLine(oField.Name + " = " + oField.GetValue(this).ToString());
break;
case System.Reflection.MemberTypes.Property:
var oProperty = (System.Reflection.PropertyInfo)oMember;
Console.WriteLine(oProperty.Name + " = " + oProperty.GetValue(this, null).ToString());
break;
}
}
You can store data in Dictionary. For every property only set/get value from dictionary.
Something like this:
public class MyData {
private Dictionary<string, object> myData;
public MyData {
this.myData = new Dictionary<string, object>();
}
public decimal LastVersion { get { return (decimal)this.myData["LastVersion"]; } private set { this.myData["LastVersion"] = value; } }
public PrimaryAbility STR { get { return (PrimaryAbility)this.myData["STR"]; } private set { this.myData["STR"] = value; } }
public PrimaryAbility DEX { get { return (PrimaryAbility)this.myData["DEX"]; } private set { this.myData["DEX"] = value; } }
public PrimaryAbility CON { get { return (PrimaryAbility)this.myData["CON"]; } private set { this.myData["CON"] = value; } }
public PrimaryAbility INT { get { return (PrimaryAbility)this.myData["INT"]; } private set { this.myData["INT"] = value; } }
public PrimaryAbility WIS { get { return (PrimaryAbility)this.myData["WIS"]; } private set { this.myData["WIS"] = value; } }
public PrimaryAbility CHA { get { return (PrimaryAbility)this.myData["CHA"]; } private set { this.myData["CHA"] = value; } }
public DerivedAbility HP { get { return (DerivedAbility)this.myData["HP"]; } private set { this.myData["HP"] = value; } }
public DerivedAbility MP { get { return (DerivedAbility)this.myData["MP"]; } private set { this.myData["MP"] = value; } }
public DerivedAbility SP { get { return (DerivedAbility)this.myData["SP"]; } private set { this.myData["SP"] = value; } }
public DerivedAbility AC { get { return (DerivedAbility)this.myData["AC"]; } private set { this.myData["AC"] = value; } }
}
Some day I found this: "Enum.GetValues(typeof(TvStations))", maybe you should search some like this.

How do I reference a field in LINQ that is named using a reserved word?

table:UserTypes
Fields:row,name,Type
This code is not working:
Int64 row = 1;
var myType = (from b in dc.UserTypes where b.Row == user.Row select b).Single();
myType.Type = "personalPage";
dc.SubmitChanges();
But, this code does...
dc.ExecuteQuery<UserType >("update dbo.UserType set Type='personalPage' where row={0}",user.Row );
I get this error:
Type the word is a word reserved.i can not user wordType
EDIT
dbml
[Table(Name="dbo.UserType")]
public partial class UserType
{
private long _Row;
private string _Type;
public UserType()
{
}
[Column(Storage="_Row", DbType="BigInt NOT NULL")]
public long Row
{
get
{
return this._Row;
}
set
{
if ((this._Row != value))
{
this._Row = value;
}
}
}
[Column(Storage="_Type", DbType="NVarChar(500) NOT NULL", CanBeNull=false)]
public string Type
{
get
{
return this._Type;
}
set
{
if ((this._Type != value))
{
this._Type = value;
}
}
}
}
Go into your LINQ to SQL DBML mapping and change the mapping for UserType.Type from being to a column named "Type" to a column named "[Type]". You can do this in the designer, or manually.
You can reference it as UserType.#Type in your code.

Categories

Resources