2

My main window has a tab control with many tabs. Each tab has a user control. In each user control, there are one or more datagrids that show certain data from DB. I do not want to load all the grids' data when my program started. I only want to execute the read DB data method when the user controls are first shown. Is there an event to do this? I tried Loaded event. But is is triggered at the starting up of my application, not when I click a tab page and show the user control.

Dave Clemmer
  • 3,741
  • 12
  • 49
  • 72
Ryan
  • 1,963
  • 3
  • 25
  • 35
  • @MitchWheat Tried that too. It is not triggered when I switch to a tab page, even the user control is the only thing in the tabpage. I have to click something in the user control to trigger that event. – Ryan Jul 31 '13 at 00:31
  • 1
    Standard `TabControl`? It loads and unloads tabs as you select them, so the `Loaded` event would have been exactly what I would have suggested. That, or load data lazily in your view model. – Kent Boogaart Jul 31 '13 at 00:42
  • @MitchWheat I think that event related with focus this is not the best way. It occurs too many times. `Selected` or `Selecting` event would be better, because it fires only when page is changed. What you think about it? (im not experienced, so I may be wrong) – Kamil Jul 31 '13 at 00:55

2 Answers2

2

There is another event that you can attach to the TabControl instead of the actual tab. Using the SelectionChanged event you can gain access to both the tabs removed (hidden) and the tabs shown (active).

You will then need to add a flag in your class to check if the tab has already been shown. Something like this should work.

        readonly List<string> shownTabs;

        public MainWindow()
        {
            InitializeComponent();
            this.shownTabs = new List<string>();
            this.tabCtrl.SelectionChanged += tabCtrl_SelectionChanged;
        }

        void tabCtrl_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if(e.AddedItems.Count == 0)
                return;
            var tabItem = e.AddedItems[0] as TabItem;
            if (tabItem == null)
                return;
            if(this.shownTabs.Contains(tabItem.Name))
                return;
            this.shownTabs.Add(tabItem.Name);

            if (tabItem == this.tab1)
            {
                //TODO : tab 1 logic
            }
            else if (tabItem == this.tab2)
            {
                //TODO : tab 2 logic
            }
        }

Just note i used a list to hold references to the tabs that are loaded. Also in this instance the tabCtrl event will fire when the tabControl is built as the first tab is added to the selection. Therefore you may find that adding the event handler in the Constructor is a bad place and may need to be in another event. IE the loaded event.

Hope this helps.

Nico
  • 12,493
  • 5
  • 42
  • 62
  • I think this is not what he is asking about. – Kamil Jul 31 '13 at 00:59
  • I would disagree. The OP wants to run some BL when the tab is click thus showing the user controls. Therefore the best event is when the tabControl has changed its selection. Any other events are not valid. In addition there is no "Selecting" or "Selected" event for a TabItem or TabControl. Here is another topic with the same question. http://stackoverflow.com/questions/772841/is-there-selected-tab-changed-event-in-the-standard-wpf-tab-control – Nico Jul 31 '13 at 01:06
  • The problem here is that you are notified when the selected tab is changed, not when its content has been completely loaded. You should refine the code above by subscribing (and unsubscribing) the Loaded event for any of the contained components. Another approach would be using a small delay, but it's just a patch. I'd follow the Kent Boogart tip about relying on a ViewModel. – Mario Vernari Jul 31 '13 at 04:34
1
 <Grid>
    <TabControl SelectionChanged="TabControl_SelectionChanged_1">
        <TabItem x:Name="tabitem1" Header="abc" />
        <TabItem x:Name="tabitem2"  Header="xyz"/>
    </TabControl>
</Grid>

 public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }
    private bool tab1ItemLoaded = false;
    private bool tab2ItemLoaded = false;

    private void TabControl_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
    {
        if (tabitem1.IsSelected && !tab1ItemLoaded)
        {
            //load tab1 data
            tab1ItemLoaded = true;
        }
        else if (tabitem2.IsSelected && !tab2ItemLoaded)
        {
            //load tab2 data
            tab2ItemLoaded = true;
        }
    }
}

I hope this will give you an idea. It would be damn easy using MVVM using Commands but if you doing in code behind then u can try SelectionChanged event of TabControl

yo chauhan
  • 12,079
  • 4
  • 39
  • 58