tarun_tenniso
tarun_tenniso

Reputation: 214

WPF data binding delay

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

Answers (1)

Sheridan
Sheridan

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

Related Questions