views:

158

answers:

2

Hello, say I have this control:

public partial class bloc999 : UserControl
{
 bloc999Data mainBlock = new bloc999Data();

 public bloc999()
 {
  InitializeComponent();
  mainBlock.txtContents = "100";

  base.DataContext = mainBlock;
 }
}

in the xaml:

    <TextBox Margin="74,116,106,0" Name="txtContents" 
Text="{Binding Path=txtContents, UpdateSourceTrigger=PropertyChanged,Mode = TwoWay}" />
    <TextBox Margin="74,145,106,132" Name="txtContents2" 
Text="{Binding Path=txtContents2, UpdateSourceTrigger=PropertyChanged,Mode = TwoWay}" />

Then I have this class:

public class bloc999Data : INotifyPropertyChanged
    {
     string _txtContents;
     string _txtContents2;

     public event PropertyChangedEventHandler PropertyChanged;

     void NotifyPropertyChanged(string propName)
     {
            if (this.PropertyChanged != null)
                this.PropertyChanged(
                    this, new PropertyChangedEventArgs(propName));
     }

     public string txtContents2
     {
            get
            {
              return this._txtContents2;
            }
            set
            {
                if (int.Parse(value) > int.Parse(this._txtContents))
                {
                    this._txtContents2 = "000";
                }
                else
                    this._txtContents2 = value;

                NotifyPropertyChanged("txtContents2");
            }
        }

        public string txtContents 
        {
            get
            {
                return this._txtContents;
            }
            set 
            {
                this._txtContents = value;
                NotifyPropertyChanged("txtContents");
            } 
        }
    }

Ok now say I have A button on the form and I do this in the code:

mainBlock.txtContents2 = "7777777";

It puts 000 in the textbox, but If i just type in manually, in the textbox (txtContents2), the setter code is called but for some reason the textboxes value does not change, the instance value does change. help?

A: 

I believe it's just because the value is changing within the context of the data binding operation, so WPF just ignores it because it knows the value is changing and thinks the event is superfluous. What it doesn't know is that you've gone and changed the value from the value WPF has to something else again.

If you do the notification in a separate message then WPF will process it outside the context of the current data binding operation and will thus pick up the change:

if (int.Parse(value) > int.Parse(this._txtContents))
{
    this._txtContents2 = "000";

    // notify WPF of our change to the property in a separate message
    Dispatcher.BeginInvoke((ThreadStart)delegate
    {
        NotifyPropertyChanged("txtContents2");
    });
}
else
{
    this._txtContents2 = value;
    NotifyPropertyChanged("txtContents2");
}

This assumes your view model has access to the Dispatcher. An example of how to do so is shown in my blog post on a base ViewModel class.

HTH,
Kent

Kent Boogaart
I just tried this, but for some reason it works with BeginInvoke, but not with Invoke...
Enriquev
Sorry, I meant `BeginInvoke` - edited. I think `Invoke` will only work if you set the `DispatcherPriority` to something lower than `DataBind`.
Kent Boogaart
A: 

I was having similar problem earlier here

In your usercontrol, update Binding and set UpdateSourceTrigger to Explicit

<TextBox Margin="74,145,106,132" x:Name="txtContents2" TextChanged="txtContents2_TextChanged"

Text="{Binding Path=txtContents2, UpdateSourceTrigger=Explicit,Mode = TwoWay}" />

then in the TextChanged event handler update the binding manually by validating the input. move validation logic from property txtContent2's setter in bloc999Data in this event handler

    private void txtContents2_TextChanged(object sender, TextChangedEventArgs e)
    {
        if (int.Parse(txtContents2.Text) > int.Parse(mainBlock.txtContents))
        {
            mainBlock.txtContents2 = "000";
            txtContents2.GetBindingExpression(TextBox.TextProperty).UpdateTarget();
        }
        else
        {
            mainBlock.txtContents2 = txtContents2.Text;
            txtContents2.GetBindingExpression(TextBox.TextProperty).UpdateSource();
        }
    }

and it works.

Hope it helps!!

viky
This works, but I actually needed my code to stay inside my class, and from it I dont have acces to my TextBox, so I cant update it.
Enriquev