简体   繁体   中英

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!!!!

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM