Reputation: 214
I am creating an app in WPF. I have created a form which have text boxes for data entry, there is a save button which will save the data. I am using data binding to properties. The problem I face is that when the user clicks on the save button very quickly after entering into the textbox, I get a null value even though the textbox is containing text. Dont worry about the path of data binding and all bcoz if I click on save after a time delay, the values are fetched correctly - so no binding issues. My queries are:
1) Should I be using binding at all on text boxes which doesnt require validations, coz i am using IDataErrorInfo and just do like this: string value = txtBox_abc.Text
;
2) I there to delay the save button click, so that I collect values from the text boxes only after all the properties have been successfully bounded to the views - is there a way at all to know this.
Binding class:
namespace Trans_It.Binding
{
class B_Ledger : IDataErrorInfo
{
public string LedgerName { get; set; }
public string LedgerCont1 { get; set; }
public string LedgerCont2 { get; set; }
public string LedgerEmail1 { get; set; }
public string LedgerEmail2 { get; set; }
public string LedgerAdd1 { get; set; }
public string LedgerAdd2 { get; set; }
public string LedgerCity { get; set; }
public string LedgerPincode { get; set; }
public string Error
{
get { throw new NotImplementedException(); }
}
public string this[string colName]
{
get
{
string result = null;
if (colName == "LedgerName")
{
if (string.IsNullOrEmpty(LedgerName))
{
result = "Ledger name mandatory!";
}
else if(string.IsNullOrEmpty(LedgerName.Trim()))
{
result = "Invalid Ledger name!";
}
}
if (colName == "LedgerCont1")
{
if (string.IsNullOrEmpty(LedgerCont1))
{
result = "Provide atleast one contact no.!";
}
else if (LedgerCont1.Length < 8)
{
result = "Contact no. should be of atleast 8 characters!";
}
}
return result;
}
}
}
}
In this file, in click handler of the button, I save the fields to database. Suppose even if I have value in my textBox, but because of the delay, I get an error message like:
Message: Parameterized query expects a parameter value which was not supplied. Parameter name: @led_pincode
And if I wait for 3-4 seconds, The transaction is successful. It means its just because of the delay, isn't it??
The xaml.cs code behind of my page where i face the problem:
namespace Trans_It.Pages
{
/// <summary>
/// Interaction logic for Page_AddLedger.xaml
/// </summary>
public partial class Page_AddLedger : Page
{
B_Ledger _ledger = new B_Ledger();
private int _errors = 0;
public Page_AddLedger()
{
InitializeComponent();
grid_ledDetails.DataContext = _ledger;
}
private void Confirm_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = _errors == 0;
e.Handled = true;
}
private void Confirm_Executed(object sender, ExecutedRoutedEventArgs e)
{
_ledger = new B_Ledger();
grid_ledDetails.DataContext = _ledger;
e.Handled = true;
}
private void Validation_Error(object sender, ValidationErrorEventArgs e)
{
if (e.Action == ValidationErrorEventAction.Added)
_errors++;
else
_errors--;
}
private void btn_addLedger_Click(object sender, EventArgs e)
{
List<SqlCeCommand> list_insertStmnts = new List<SqlCeCommand>();
list_insertStmnts.Add(getPartyInsertStatement());
bool lb_txnSuccess = M_DbMain.performInsertTxn(list_insertStmnts);
if (lb_txnSuccess)
{
MessageBox.Show("Txn Success");
}
else
{
MessageBox.Show("Txn Failure");
}
// <TESTING>
//this.NavigationService.GoBack();
// </TESTING>
}
private SqlCeCommand getPartyInsertStatement()
{
string ls_insertStmnt;
ls_insertStmnt = "INSERT INTO " + M_LedgerMaster.TABLE_NAME +
"(" +
M_LedgerMaster.LED_NAME + ", " +
M_LedgerMaster.LED_CONTACT1 + ", " +
M_LedgerMaster.LED_CONTACT2 + ", " +
M_LedgerMaster.LED_EMAIL1 + ", " +
M_LedgerMaster.LED_EMAIL2 + ", " +
M_LedgerMaster.LED_ADD1 + ", " +
M_LedgerMaster.LED_ADD2 + ", " +
M_LedgerMaster.LED_CITY + ", " +
M_LedgerMaster.LED_PINCODE +
")" +
" VALUES " +
"(" +
"@" + M_LedgerMaster.LED_NAME + ", " +
"@" + M_LedgerMaster.LED_CONTACT1 + ", " +
"@" + M_LedgerMaster.LED_CONTACT2 + ", " +
"@" + M_LedgerMaster.LED_EMAIL1 + ", " +
"@" + M_LedgerMaster.LED_EMAIL2 + ", " +
"@" + M_LedgerMaster.LED_ADD1 + ", " +
"@" + M_LedgerMaster.LED_ADD2 + ", " +
"@" + M_LedgerMaster.LED_CITY + ", " +
"@" + M_LedgerMaster.LED_PINCODE +
");";
SqlCeCommand cmd = new SqlCeCommand();
cmd.Parameters.Add(new SqlCeParameter("@" + M_LedgerMaster.LED_NAME, _ledger.LedgerName));
cmd.Parameters.Add(new SqlCeParameter("@" + M_LedgerMaster.LED_CONTACT1, _ledger.LedgerCont1));
cmd.Parameters.Add(new SqlCeParameter("@" + M_LedgerMaster.LED_CONTACT2, _ledger.LedgerCont2));
cmd.Parameters.Add(new SqlCeParameter("@" + M_LedgerMaster.LED_EMAIL1, _ledger.LedgerEmail1));
cmd.Parameters.Add(new SqlCeParameter("@" + M_LedgerMaster.LED_EMAIL2, _ledger.LedgerEmail2));
cmd.Parameters.Add(new SqlCeParameter("@" + M_LedgerMaster.LED_ADD1, _ledger.LedgerAdd1));
cmd.Parameters.Add(new SqlCeParameter("@" + M_LedgerMaster.LED_ADD2, _ledger.LedgerAdd2));
cmd.Parameters.Add(new SqlCeParameter("@" + M_LedgerMaster.LED_CITY, _ledger.LedgerCity));
cmd.Parameters.Add(new SqlCeParameter("@" + M_LedgerMaster.LED_PINCODE, _ledger.LedgerPincode));
cmd.CommandText = ls_insertStmnt;
return cmd;
}
}
}
//////////////////////////////////////////////////////////// The .xaml file:
<Page x:Class="Trans_It.Pages.Page_AddLedger"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Height="600"
Width="1000"
Title="Page_AddLedger">
<Grid x:Name="grid_ledDetails">
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".5*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width=".5*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width=".5*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width=".5*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="2*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height=".5*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height=".5*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height=".5*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height=".5*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height=".5*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="2*"/>
</Grid.RowDefinitions>
<Grid.CommandBindings>
<CommandBinding Command="New" CanExecute="Confirm_CanExecute" Executed="Confirm_Executed"/>
</Grid.CommandBindings>
<!-- Labels -->
<TextBlock Grid.Column="1" Grid.Row="1" VerticalAlignment="Center" HorizontalAlignment="Right">Ledger Name</TextBlock>
<TextBlock Grid.Column="1" Grid.Row="3" VerticalAlignment="Center" HorizontalAlignment="Right">Contact</TextBlock>
<TextBlock Grid.Column="1" Grid.Row="5" VerticalAlignment="Center" HorizontalAlignment="Right">Email</TextBlock>
<TextBlock Grid.Column="1" Grid.Row="7" VerticalAlignment="Center" HorizontalAlignment="Right">Address</TextBlock>
<TextBlock Grid.Column="1" Grid.Row="9" VerticalAlignment="Center" HorizontalAlignment="Right">City And Pincode</TextBlock>
<!-- Left side Text Boxes -->
<TextBox x:Name="txtBox_ledgerName" Grid.Column="3" Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
Validation.Error="Validation_Error" Text="{Binding UpdateSourceTrigger=PropertyChanged, Path=LedgerName,
ValidatesOnDataErrors=true, NotifyOnValidationError=true}"></TextBox>
<TextBox x:Name="txtBox_contact1" Grid.Column="3" Grid.Row="3" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
Validation.Error="Validation_Error" Text="{Binding UpdateSourceTrigger=PropertyChanged, Path=LedgerCont1,
ValidatesOnDataErrors=True, NotifyOnValidationError=True}"></TextBox>
<TextBox x:Name="txtBox_email1" Grid.Column="3" Grid.Row="5" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
Text="{Binding Path=LedgerEmail1}"></TextBox>
<TextBox x:Name="txtBox_add1" Grid.Column="3" Grid.Row="7" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
Text="{Binding Path=LedgerAdd1}"></TextBox>
<TextBox x:Name="txtBox_city" Grid.Column="3" Grid.Row="9" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
Text="{Binding Path=LedgerCity}"></TextBox>
<Button x:Name="btn_addLedger" Grid.Column="3" Grid.Row="11" HorizontalAlignment="Stretch" Click="btn_addLedger_Click"
Command="New">Add Party</Button>
<!-- Right side Text Boxes -->
<TextBox x:Name="txtBox_contact2" Grid.Column="5" Grid.Row="3" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
Text="{Binding Path=LedgerCont2}"></TextBox>
<TextBox x:Name="txtBox_email2" Grid.Column="5" Grid.Row="5" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
Text="{Binding Path=LedgerEmail2}"></TextBox>
<TextBox x:Name="txtBox_add2" Grid.Column="5" Grid.Row="7" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
Text="{Binding Path=LedgerAdd2}"></TextBox>
<TextBox x:Name="txtBox_pincode" Grid.Column="5" Grid.Row="9" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
Text="{Binding Path=LedgerPincode}"></TextBox>
</Grid>
</Page>
///////////////////////////////////////////////////////////////////////
Never posted any code, so forgive me if If I am not clear. If something missing, I will surely post it.
I have read about the message queue. But cant find any solution, please help.
Cheers!! Thanks in Advance!!!!
Upvotes: 1
Views: 5161
Reputation: 69959
From .NET 4.5, the BindingBase
class now contains a Delay
property. This enables you to set an integer that represents the number of milliseconds that the Framework will wait before updating a data source. However, it appears that your data source updates are already arriving late. So if you are using this property already, I'd remove it.
Failing that, I would agree with @HighCore's comment that you probably have a bug in your code somewhere that is causing this delay, because data binding normally happens instantly. You could try setting the Binding.UpdateSourceTrigger
property to PropertyChange
, but apart from that, I doubt that anybody can help you much further because you felt it unnecessary to provide your code, unlike all of the other users on this website.
Upvotes: 5