This is a migrated thread and some comments may be shown as answers.

Run function in tab from Parent

6 Answers 58 Views
TabControl
This is a migrated thread and some comments may be shown as answers.
Sean
Top achievements
Rank 1
Sean asked on 09 Jun 2010, 01:49 AM
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.

6 Answers, 1 is accepted

Sort by
0
Viktor Tsvetkov
Telerik team
answered on 14 Jun 2010, 03:25 PM
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.
0
Sean
Top achievements
Rank 1
answered on 21 Jun 2010, 07:13 PM
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!
0
codeputer
Top achievements
Rank 2
answered on 02 Mar 2011, 01:46 AM
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
0
Petar Mladenov
Telerik team
answered on 04 Mar 2011, 05:44 PM
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!
0
codeputer
Top achievements
Rank 2
answered on 04 Mar 2011, 06:00 PM
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
0
Petar Mladenov
Telerik team
answered on 09 Mar 2011, 04:12 PM
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!
Tags
TabControl
Asked by
Sean
Top achievements
Rank 1
Answers by
Viktor Tsvetkov
Telerik team
Sean
Top achievements
Rank 1
codeputer
Top achievements
Rank 2
Petar Mladenov
Telerik team
Share this question
or