Run function in tab from Parent

7 posts, 0 answers
  1. Sean
    Sean avatar
    7 posts
    Member since:
    Mar 2009

    Posted 08 Jun 2010 Link to this post

    Hello,
    I have a TabControl with a series of User Controls in each tab. I am investigating using the PreviewSelectionChanged event to stop a tab change if a tab does not pass some validation. I am basing my ideas off of this code below:

    private void TabControl_PreviewSelectionChanged(object sender, Telerik.Windows.Controls.SelectionChangedEventArgs e)     
            {     
                RadTabItem navTo = e.AddedItems[0] as RadTabItem;     
                if (navTo.Visibility == Visibility.Collapsed)     
                {     
                    e.Handled = true;     
                }     
            }     
     

    But insead of checking a built in property of the RadTabItem, I want to run a function in my user control, likely an IsValid() function returning a bool to decide whether to cancel the tab switch or not. I am using the MVVM pattern in the UserControls if that makes a difference, but I don't mind running the validation in the UserControl itself if that is the way to do it.

    Thanks.
  2. Viktor Tsvetkov
    Admin
    Viktor Tsvetkov avatar
    382 posts

    Posted 14 Jun 2010 Link to this post

    Hello Sean,

    The example attached shows how to handle the PreviewSelected event based on a condition coming from the ViewModel. The ViewModel in the attached project is a class called DataItem and it contains one public property called IsValid. On PreviewSelected, if the item in e.AddedItems[0] has its property IsValid set to true, we do not handle the preview event. Otherwise we handle it.

    public partial class MainPage : UserControl
        {
            public MainPage()
            {
                InitializeComponent();
     
                ObservableCollection<DataItem> items = new ObservableCollection<DataItem>();
                items.Add(new DataItem("First", true));
                items.Add(new DataItem("Second", false));
                items.Add(new DataItem("Third", true));
     
                tabControl.ItemsSource = items;
            }
     
            private void tabControl_PreviewSelectionChanged(object sender, Telerik.Windows.Controls.SelectionChangedEventArgs e)
            {
                var tabItem = e.AddedItems[0] as DataItem;
                if (!tabItem.IsValid)
                {
                    e.Handled = true;
                }
            }
        }
     
        public class DataItem
        {
            public DataItem(string name, bool isValid)
            {
                this.Name = name;
                this.IsValid = isValid;
            }
     
            public string Name { get; set; }
            public bool IsValid { get; set; }
        }

    Another way to look at this scenario is if you have specified your tab items in xaml.

    <telerikNavigation:RadTabControl x:Name="tabControl"
                PreviewSelectionChanged="tabControl_PreviewSelectionChanged">
                <telerikNavigation:RadTabItem Header="Item 0">
                    <myUserControls:UserControl_0 />
                </telerikNavigation:RadTabItem>
                <telerikNavigation:RadTabItem Header="Item 1">
                    <myUserControls:UserControl_1 />
                </telerikNavigation:RadTabItem>
                <telerikNavigation:RadTabItem Header="Item 2">
                    <myUserControls:UserControl_2 />
                </telerikNavigation:RadTabItem>
            </telerikNavigation:RadTabControl>

    Then in the PreviewSelected event handler, you will receive the tab item and the user control will be its content.

    private void tabControl_PreviewSelectionChanged(object sender, Telerik.Windows.Controls.SelectionChangedEventArgs e)
    {
        var tabItem = e.AddedItems[0] as RadTabItem;
        if (tabItem != null)
        {
            MyUserControl myUserControl = tabItem.Content as MyUserControl;
            if(myUserControl != null)
            {
                // ValidationFunction is your function that will execute the logic for determining whether to handle the preview event or not
                if(myUserControl.ValidationFunction() == true)
                {
                    e.Handled = false;
                }
                else
                {
                    e.Handled = true;
                }
            }
        }
    }

    I am not sure which one is your scenario, so if you find it difficult to continue after these explanations, let us know which is you scenario and we will be glad to further assist you.

    Best wishes,
    Viktor Tsvetkov
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
  3. DevCraft banner
  4. Sean
    Sean avatar
    7 posts
    Member since:
    Mar 2009

    Posted 21 Jun 2010 Link to this post

    Thanks for your response.
    The approach I took was to get each tab to derive off of a common interface. The interface has a bool IsValid() function (among others).
    Once I cast the navFrom tab into the interface type I can get access to the IsValid function. Each tab then implements it's own version of the IsValid function.

    interface IUITab  
        {  
            bool IsValid();  
            void RefreshView();  
            void Save();  
        } 

     IUITab currentTab = navFrom.Content as IUITab;  
                        if (currentTab != null && currentTab.IsValid() == false)  
                            e.Handled = true

    Thanks for pointing me in the right direction!
  5. codputer
    codputer avatar
    45 posts
    Member since:
    Apr 2007

    Posted 01 Mar 2011 Link to this post

    I'm in the same scenario, wanting to validate my view model before allowing a tab switch.  However, if I make a change in a (say) textbox, then use the mouse to click the next tab - the tab switch occurs before the textbox control flushes to the viewmodel!

    Hence when I validate the model, it does not see the change yet!

    I realize that this is not the tab controls problem - but I'm looking for help to flush the bindings before the preview selection event?

    Shouldn't the control flush the binding when it loses focus?  Why does a mouse move from the field not cause a binding to flush?

    Richard
  6. Petar Mladenov
    Admin
    Petar Mladenov avatar
    2891 posts

    Posted 04 Mar 2011 Link to this post

    Hi codputer,

    I prepared a sample for you that shows how to update the binding in the TextChanged event handler of the TextBox. Basically it sets Explicit UpdateSourceTrigger like so:
    <telerik:RadTabControl.ContentTemplate>
                 <DataTemplate>
                     <TextBox Width="200" 
                              Height="40"
                              VerticalAlignment="Center"
                              Text="{Binding Description, Mode=TwoWay, UpdateSourceTrigger=Explicit}"
                              TextChanged="TextBox_TextChanged" />
                 </DataTemplate>
             </telerik:RadTabControl.ContentTemplate>
    Then In code behind you have to update the source like so:
    private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
           {
               TextBox textBox = sender as TextBox; 
               BindingExpression binding = textBox.GetBindingExpression(TextBox.TextProperty); 
               binding.UpdateSource(); 
           }
    The described apporach is realized in the attached solution. So please gibe it a try and let us know if it satisfies you.

    Best wishes,
    Petar Mladenov
    the Telerik team
    Registration for Q1 2011 What’s New Webinar Week is now open. Mark your calendar for the week starting March 21st and book your seat for a walk through all the exciting stuff we ship with the new release!
  7. codputer
    codputer avatar
    45 posts
    Member since:
    Apr 2007

    Posted 04 Mar 2011 Link to this post

    Hello! Thanks for the quick reply.

    I'm familiar with this but i would hate to have to implement this on all my text box controls.  Another fix is to flush the binding on each keystroke, hence getting the update before leaving the control. Can you confirm if Telerik's textbox control does this?  Perhaps I should just only use telerik controls? :)

    I had a simliar in WinForms, the fix was to also flush the binding, but I could do it centrally via the binding source.

    I was amazed however that this well documented problem still exists in the framework.  If you leave a control via a mouse move, it simply cannot "react" fast enough in order to get the messages dispatched in the correct timeline order.

    I've put up a discussion on StackOverFlow - but had to find anybody to discuss in detail as very few developers know what the message pump is anymore.

    R
  8. Petar Mladenov
    Admin
    Petar Mladenov avatar
    2891 posts

    Posted 09 Mar 2011 Link to this post

    Hi codputer,

    You can use our new MaskedInput controls available from Q1 2001 Beta. Check out this help article that describes how to use the validation feature and the corresponding demo. Hope this can fit in your scenario.

    Kind regards,
    Petar Mladenov
    the Telerik team
    Registration for Q1 2011 What’s New Webinar Week is now open. Mark your calendar for the week starting March 21st and book your seat for a walk through all the exciting stuff we ship with the new release!
Back to Top
DevCraft banner