WPF Data-binding Validation problem

Discussion in 'Microsoft Dot NET Framework' started by Jim Hudson, Oct 30, 2008.

  1. Jim Hudson

    Jim Hudson Guest

    I have a little <UserControl> that gets hosted in a Canvas (so that I can
    position it the way I want), constructed when the app starts, and then
    displayed and hidden through appropriate settings of its Visibility property.

    Inside the <UserControl>, I have a couple of <TextBox> controls, each of
    which is subject to validation:

    <TextBox x:Uid="DestinationTextBox"
    x:Name="DestinationTextBox" Style="{StaticResource TextBoxStyle}"

    Validation.ErrorTemplate="{StaticResource errorTemplate}"
    MinWidth="200" >
    <TextBox.Text>
    <Binding x:Name="DestinationBinding"
    x:Uid="DestinationBinding" Path="Rule.Destination"
    NotifyOnSourceUpdated="True"
    UpdateSourceTrigger="PropertyChanged" >
    <Binding.ValidationRules>
    <peme:DestinationValidationRule
    x:Uid="DestinationValidationRule" x:Name="DestinationValidationRule" />
    </Binding.ValidationRules>
    </Binding>
    </TextBox.Text>
    </TextBox>


    I want the error template to be displayed whenever the bound data
    ("Rule.Destination") is invalid: both when the <UserControl> is initially
    displayed, and also whenever the user enters bad data. To make that happen,
    the containing application makes the <UserControl> visible, and then calls a
    method of the <UserControl> that does the following:

    // Getting data-binding to work the way I want it to is NOT
    easy. First, we have to
    // force the XAML objects to reload themselves from the bound
    data. I can cause that
    // to happen by clearing and then resetting the DataContext for
    the XAML objects.
    this.DataContext = null;
    this.DataContext = this;

    // THEN, I need to force the validation rules to be fired. That
    only happens
    // when the binding source (which is this.Rule.xxxx) gets
    updated by the data-binding.
    // Since the controls now have copies of the values in
    this.Rule, I'll just force
    // them to copy them back by calling UpdateSource(). The
    validation will happen
    // along the way.

    this.DestinationTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();

    MY PROBLEM:

    EVERY time that the <UserControl> is made visible, the
    BindingExpression.UpdateSource() method gets called and correctly sets the
    Validation.HasErrors attached property to "true". I've verified this by
    displaying that property in the UI. HOWEVER, THE FIRST TIME its displayed,
    the error-template adorner is not shown. If I then change the Visibility of
    the <UserControl> to Collapsed (to hide it) and then Visible (to re-display
    it), then the error-template adorner appears.

    What do I have to do to get the error-template adorner to appear EVERY time?
    --
    Jim Hudson
     
    Jim Hudson, Oct 30, 2008
    #1
    1. Advertisements

  2. Hi Jim,

    Thank you for using Microsoft Managed Newsgroup Service, my name is Zhi-Xin
    Ye, I'm assigned to help you on this issue.

    As I understand, you want the error template to be displayed when the
    UserControl is initially displayed.

    You can handle the Loaded event on the UserControl or on the Window, and
    call the UpdateSource() method in the event handler. For example:

    void UserControl1_Loaded(object sender, RoutedEventArgs e)
    {

    this.textBox1.GetBindingExpression(TextBox.TextProperty).UpdateSource();
    }

    Please try my suggestion and let me know the result.

    Sincerely,
    Zhi-Xin Ye
    Microsoft Managed Newsgroup Support Team

    Delighting our customers is our #1 priority. We welcome your comments and
    suggestions about how we can

    improve the support we provide to you. Please feel free to let my manager
    know what you think of the level

    of service provided. You can send feedback directly to my manager at:
    .

    ==================================================
    Get notification to my posts through email? Please refer to

    http://msdn.microsoft.com/en-us/subscriptions/aa948868.aspx#notifications.

    Note: MSDN Managed Newsgroup support offering is for non-urgent issues
    where an initial response from the

    community or a Microsoft Support Engineer within 2 business day is
    acceptable. Please note that each follow

    up response may take approximately 2 business days as the support
    professional working with you may need

    further investigation to reach the most efficient resolution. The offering
    is not appropriate for situations

    that require urgent, real-time or phone-based interactions. Issues of this
    nature are best handled working

    with a dedicated Microsoft Support Engineer by contacting Microsoft
    Customer Support Services (CSS) at

    http://msdn.microsoft.com/en-us/subscriptions/aa948874.aspx
    ==================================================
    This posting is provided "AS IS" with no warranties, and confers no rights.
     
    Zhi-Xin Ye [MSFT], Oct 31, 2008
    #2
    1. Advertisements

  3. Jim Hudson

    Jim Hudson Guest

    Thanks for getting back to me, Zhi-Xin Ye.

    The sequence of events, when my program runs, is this:

    1) My UserControl is defined in the XAML, placed on a <Canvas>. Therefore,
    it is constructed by the g.cs code for the <Page>. Its Visibility is
    specified as "Collapsed" in the XAML code.
    2) When the <Page> is displayed, the Load event for the UserControl is
    fired. At that point, the DataContext for the UserControl is null, so the
    binding for the TextBox does nothing. I ADDED THE CODE YOU SUGGESTED. IT
    FIRED AT THIS POINT AND DID NOT FIX THE PROBLEM.
    3) Later, as a result of the user operating another control on the <Page>,
    the code-behind logic that I showed in my original message is fired: the
    DataContext for the <UserControl> is set, the Visibility for the
    <UserControl> is set to "Visible", and the UpdateSource() method is called
    for the textbox's binding expression.
    4) The FIRST time the <UserControl> is made visible, the adorners defined in
    the error template are NOT displayed. However, the NEXT time (and all
    subsequent times), the adorners ARE displayed.
    5) At one point, I added an experimental TextBox to the UserControl, binding
    the Text property of the experimental TextBox to the Validation.HasError
    property of the other TextBox. Every time the UserControl was displayed,
    that experimental TextBox contained "true" (the FIRST and all subsequent
    times). So, I'm sure that the Validation is firing on that FIRST display,
    and I'm sure that it's setting the property that triggers the error template.


    Clearly, something happens after my code-behind logic executes and before
    the UserControl is displayed for the first time. Whatever it is, that
    "mystery event" has to occur before my error template adorners appear.
    Perhaps some error template layer gets created? Whatever it is, I need to
    force it to happen sooner in the processing. Do you have any idea what that
    "mystery event" might be?
    --
    Jim Hudson
     
    Jim Hudson, Oct 31, 2008
    #3
  4. Hi Jim,

    I can reproduce the problem with the steps, it seems that there's something
    stops the error adorner from displaying for the first time. I will do more
    research to see what happens.
    However, an idea to fix the problem is using a timer to call the
    UpdateSource() method for the textbox's binding expression right after
    clicking the button. For example:

    private void button1_Click(object sender, RoutedEventArgs e)
    {
    if (uc1.Visibility == Visibility.Collapsed)
    uc1.Visibility = Visibility.Visible;
    else if (uc1.Visibility == Visibility.Visible)
    uc1.Visibility = Visibility.Collapsed;

    System.Timers.Timer t = new System.Timers.Timer();
    t.Interval = 1;
    t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed);
    t.Start();
    }

    void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
    this.Dispatcher.Invoke(new UpdateDelegate(update));
    System.Timers.Timer t = sender as System.Timers.Timer;
    t.Stop();
    }

    public delegate void UpdateDelegate();

    public void update()
    {

    uc1.textBox1.GetBindingExpression(TextBox.TextProperty).UpdateSource();
    }

    I'm doing more research on this problem and will come back to you as soon
    as possible.

    Sincerely,
    Zhi-Xin Ye
    Microsoft Managed Newsgroup Support Team

    Delighting our customers is our #1 priority. We welcome your comments and
    suggestions about how we can

    improve the support we provide to you. Please feel free to let my manager
    know what you think of the level

    of service provided. You can send feedback directly to my manager at:
    .

    This posting is provided "AS IS" with no warranties, and confers no rights.

    ============================================================================
    =

    Does my last reply make sense to you? If you need further help, please feel
    free to let me know, I will be happy to be of assistance.
     
    Zhi-Xin Ye [MSFT], Nov 4, 2008
    #4
  5. Jim Hudson

    Jim Hudson Guest

    Once again, Zhi-Xin Ye, thanks for getting back to me.

    It turned out that I had to switch my little UserControls into modeless
    dialog Windows. I create each Window when I need it, then set the data
    binding, then Show() it. The user interacts with it, and the application.
    Once they click the "OK" button in the dialog, I Close() the window.

    What I found is that the following sequence makes the ErrorTemplate adorners
    appear when they're supposed to, ALL the time:

    1) Construct the Window
    2) Set the Window.DataContext
    3) Call Window.Show()
    4) Call UpdateSource() for each BindingExpression that has a ValidationRule

    Apparently, the Show() method performs the necessary side-effect to get my
    ErrorTemplate adorners to appear. I'm all set - you can close this issue.
    --
    Jim Hudson
     
    Jim Hudson, Nov 4, 2008
    #5
    1. Advertisements

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Lloyd Dupont

    [WPF] data binding and SetValue()

    Lloyd Dupont, Jun 15, 2007, in forum: Microsoft Dot NET Framework
    Replies:
    2
    Views:
    711
    Lloyd Dupont
    Jun 16, 2007
  2. Rolf Welskes

    Wpf/net 3.5 /VS2008 - Binding to Ado.net dataTable problem

    Rolf Welskes, Nov 21, 2007, in forum: Microsoft Dot NET Framework
    Replies:
    5
    Views:
    242
    Walter Wang [MSFT]
    Nov 28, 2007
  3. Ericd

    WPF binding issue with object

    Ericd, Feb 12, 2008, in forum: Microsoft Dot NET Framework
    Replies:
    0
    Views:
    263
    Ericd
    Feb 12, 2008
  4. ryan baldwin

    Disappearing Data on Dynamically Loaded WPF Form

    ryan baldwin, Jun 19, 2008, in forum: Microsoft Dot NET Framework
    Replies:
    3
    Views:
    394
    Linda Liu[MSFT]
    Jun 25, 2008
  5. Gota

    WPF data grid

    Gota, Jun 7, 2009, in forum: Microsoft Dot NET Framework
    Replies:
    2
    Views:
    838
    Odi [Xceed[]
    Jun 22, 2009
Loading...

Share This Page