0

I have the following TabControl:

<TabControl Name="tabControl" Grid.Row="0" MinWidth="270" HorizontalAlignment="Stretch" ItemsSource="{Binding Counters}" ContentTemplate="{StaticResource templateForTheContent}"
        ItemTemplate="{StaticResource templateForTheHeader}">
</TabControl>

It uses this DataTemplate:

<Window.Resources>

            <DataTemplate x:Key="templateForTheContent" >
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="1*"/>
                    <RowDefinition  Height="Auto"/>
                </Grid.RowDefinitions>
                <ListBox Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" 
                         ItemsSource="{Binding}"
                         SelectionMode="Multiple"
                             BorderThickness="1" BorderBrush="#FF8B8B8B" SelectionChanged="ListBox_SelectionChanged_1">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <TextBlock>
                                <Run Text="{Binding CounterName, Mode=OneWay}" />
                                <Run Text="{Binding InstanceName, Mode=OneWay}" />
                            </TextBlock>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
                <Button Name="RAMSelectAllButton" Margin="0,10,0,0" Grid.Column="0" Grid.Row="1">
                    <TextBlock Text="SELECT ALL"/>
                </Button>
                <Button Name="RAMUnSelectAllButton" Margin="0,10,0,0" Grid.Column="1" Grid.Row="1">
                    <TextBlock Text="UNSELECT ALL"/>
                </Button>
            </Grid>
        </DataTemplate>

            <DataTemplate x:Key="templateForTheHeader" >
                <TextBlock Text="{Binding CategoryName}"/>
            </DataTemplate>

        </Window.Resources>

It works as expected, binding works well, everything would be totally fine if this issue wasn't present: Each time I switch a tab in my TabControl, selected items of a ListBox in my previous tab are reset - so when I go back to that tab - nothing is selected.

How to fix this?

//EDIT here's my ListBox_SelectionChanged_1 method:

private void ListBox_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
{
    System.Windows.Controls.ListBox listBoxTemp = sender as System.Windows.Controls.ListBox;
    PerformanceCounter counterTemp = (PerformanceCounter)listBoxTemp.Items[0];

    if (!appData.SelectedCounters.ContainsKey(counterTemp.CategoryName))
        appData.SelectedCounters.Add(counterTemp.CategoryName, new List<PerformanceCounter>());

    appData.SelectedCounters[counterTemp.CategoryName].Clear();

    foreach (PerformanceCounter counter in listBoxTemp.SelectedItems)
    {
        appData.SelectedCounters[counterTemp.CategoryName].Add(counter);
    }

}

ListBox is bound to Counters, which is Observable Collection:

public ObservableCollection<ObservableCollection<PerformanceCounter>> Counters
{
    get { return _Counters; }
}
ObservableCollection<ObservableCollection<PerformanceCounter>> _Counters = new ObservableCollection<ObservableCollection<PerformanceCounter>>();
mnj
  • 2,539
  • 3
  • 29
  • 58
  • I'd be able to handle this if i could access ListBox in currently selected tab. how to do it? I tried IEnumerable listBoxList = tabControl.FindChildren();, but it's empty (although there's a ListBox) – mnj Sep 09 '16 at 10:14
  • Once you are binding the ListBox to a collection you can't access the IsSelected property from the Items in code behind. You have to manage it through a binding with a corresponding property of the ViewModel –  Sep 09 '16 at 12:41
  • I used ListBox. SelectedItems – mnj Sep 10 '16 at 15:56

1 Answers1

1

(i am not familiar with TabControls, or WPF for that matter, but i would suggest a solution like this:)

Backup the selected items of your ListBox in a Dictionary.

var selectionBackups = new Dictionary<ListBox, IEnumerable<ListBoxItem>>();

I'd keep this field updated in ListBox_SelectionChanged_1(). Whenever you enter a Tab, overwrite the concerned ListBox's selection.

void TabEnter(object sender, TabEventArgs e)
{
    ListBox lb = ... //acquire the current Listbox
    OverwriteSelection(lb, selectionBackups[lb]); //set the ListBox's selection
}

(You might want to prevent the ListBox_SelectionChanged_1() from triggering when you restore the selection. That could be done like this:

bool auto_select = false; //set this to true while editing selections
private void ListBox_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
{
    if(auto_select)
        return;
    ...
}

)

  • Haha, i had exactly the same idea. I'm trying to do it, but there's one problem. It's about this TabEnter method. I think that in WPF this is tabControl_SelectionChanged(). So I added this event and I want to acquire the current ListBox (like in your code). I used FindVisualChildren method from here: [Link](http://stackoverflow.com/questions/974598/find-all-controls-in-wpf-window-by-type) But it gets me the ListBox, that exists in the PREVIOUS tab - not the current one. I have no idea how to get access to the ListBox that is inside currently selected Tab. – mnj Sep 09 '16 at 10:41
  • hmm, is the selected Tab's index specified in the EventArgs? That may help if you can find the ListBox amongst the Tab's children. – TheHowlingHoaschd Sep 09 '16 at 10:53
  • Yeah, it has SelectedIndex (and it's the correct Index, I checked). I can also acces the header of currently selected tab (tabControl.SelectedItem.First()). But why does it give me the previous ListBox, not he current one? i also looked through ListBox's events, but i don't see any which would be ok for this situation. There is Loaded() event, but it occurs only the first time a ListBox is displayed - later it doesn't. – mnj Sep 09 '16 at 11:06
  • I don't know, why it shouldn't find it. Are you calling it with the correct Tab as `depObj` parameter? (`tabControl.Items[e.SelectedIndex]` perhaps?). An afterthought: does this method only torn up actually visible objects? If the correct ListBox is still hidden, when the Event is triggered, that may explain it. – TheHowlingHoaschd Sep 09 '16 at 11:12
  • I' calling this method with the whole window as an argument. – mnj Sep 09 '16 at 11:30
  • Does passing a Tab also work? That would only include the ListBox you're looking for then. If not you would need some other way to root through it's children, but i wouldn't know, google it. – TheHowlingHoaschd Sep 09 '16 at 11:35
  • I think I found the solution. It still doesn't fully work, but now i think it's just a bug in my code, which I have to find, because my selections are shown, but not always. I actually used a completely different event - TextBlock_MouseLeftButtonUp_1 - this textblock is actually a header of a Tab. So each time i click it the current tab changes and the event is raised - from there i can access the right ListBox. – mnj Sep 09 '16 at 12:06