0

I have the following code that creates a TabControl. Each tab contains a UserControl (code is below) that displays different data (one shows Local tax info and the other show Fed/State tax info).

TabControl

    <TabControl 
        Name="MappingTabs"
        Margin="6,7,7,8" Padding="6"
        Background="White" >
        <TabItem
            Name="LocalTaxTab"
            Padding="6,1"
            Header="Local">
            <AdornerDecorator>
                <DockPanel>
                    <Border Margin="7">
                        <GroupBox 
                            Name="LocalTaxesGroup">
                            <GroupBox.Header>
                                <TextBlock 
                                    FontWeight="Bold" 
                                    Text="Local Taxes">
                                </TextBlock>
                            </GroupBox.Header>
                            <StackPanel Margin="20,8,10,0"
                                        Orientation="Vertical">

                                <local:TaxCodeMappingHeader />

                                <!-- Note that a row is 25 high, -->
                                <ScrollViewer
                                        MaxHeight="250"
                                        >
                                    <ItemsControl  
                                            Name="LocalTaxCodeMappingControl"
                                            ItemTemplate="{StaticResource MappingRuleTemplate}" 
                                            BorderThickness="0" 
                                            AlternationCount="2" 
                                            IsTextSearchEnabled="False"
                                            HorizontalContentAlignment="Stretch"
                                            ItemsSource="{Binding TaxCodesCollection[0].CodeCollection, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}">
                                        <!--  ItemsSource="{Binding Source={StaticResource sortedCodeCollection}}">    -->
                                    </ItemsControl>
                                </ScrollViewer>

                                <local:TaxCodeMappingFooter DataContext="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}"/>

                            </StackPanel>
                        </GroupBox>
                    </Border>
                </DockPanel>
            </AdornerDecorator>
        </TabItem>
        <TabItem
            Name="FedStateTaxesTab"
            Padding="6,1"
            Header="Federal\State">
            <AdornerDecorator>
                <DockPanel>
                    <Border Margin="7">
                        <GroupBox 
                            Name="FedStateTaxesGroup">
                            <GroupBox.Header>
                                <TextBlock 
                                    FontWeight="Bold" 
                                    Text="Federal \ State Taxes">
                                </TextBlock>
                            </GroupBox.Header>
                            <StackPanel Margin="20,8,10,0"
                                        Orientation="Vertical">

                                <local:TaxCodeMappingHeader />

                                <!-- Note that a row is 25 high, -->
                                <ScrollViewer
                                        MaxHeight="250"
                                        >
                                    <ItemsControl  
                                            Name="FedStateTaxCodeMappingControl"
                                            ItemTemplate="{StaticResource MappingRuleTemplate}" 
                                            BorderThickness="0" 
                                            AlternationCount="2" 
                                            IsTextSearchEnabled="False"
                                            HorizontalContentAlignment="Stretch"
                                            ItemsSource="{Binding TaxCodesCollection[1].CodeCollection, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}">
                                        <!--  ItemsSource="{Binding Source={StaticResource sortedCodeCollection}}">    -->
                                    </ItemsControl>
                                </ScrollViewer>

                                <local:TaxCodeMappingFooter DataContext="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}"/>

                            </StackPanel>
                        </GroupBox>
                    </Border>
                </DockPanel>
            </AdornerDecorator>
        </TabItem>
    </TabControl>
</StackPanel>

UserControl (TaxCodeMappingFooter)

   <Button 
        Name="AddButton"
        Grid.Row="0"
        Grid.Column="0"
        Height="20" Width="20"
        Command="{Binding Path=DataContext.AddClickCommand}"
        CommandParameter="(want the tab name here)"
        Style="{StaticResource ImageButton}"
        ToolTip="Add a rule"
        local:AttachedImage.Image="{StaticResource AddImageSource}" />

The UserControl (TaxCodeMappingFooter) contains an Add button that I need to wire up via RelayCommand to the VM. I need to somehow tell the VM which tab is calling the Add command so that an item can be added to the correct collection. I thought about sending the TabName and then keying off that to know which tab the user is on.

Is my idea correct or is the a better way to do this and if it is correct how do I get the TabName value to pass it back as a CommandParameter?

H.B.
  • 166,899
  • 29
  • 327
  • 400
BrianKE
  • 4,035
  • 13
  • 65
  • 115
  • 3
    If you're doing MVVM then I would say the better way is each tab is a View/ViewModel. [One example here](http://stackoverflow.com/questions/5650812/how-do-i-bind-a-tabcontrol-to-a-collection-of-viewmodels) – bland Nov 18 '13 at 14:00
  • You are getting it wrong. In case of MVVM you should use ViewModels for tabs instead of hardcoded ones. In that case you would have access to the currently selected item. – Andras Sebo Nov 18 '13 at 14:02

2 Answers2

0

If you are going to hard code your UI controls as you have done, then perhaps your simplest option is to define a string DependencyProperty in your TaxCodeMappingFooter control:

public static readonly DependencyProperty TabNameProperty = DependencyProperty.
    Register("TabName", typeof(string), typeof(TaxCodeMappingFooter));

public string TabName
{
    get { return (string)GetTabName(TabNameProperty); }
    set { SetTabName(TabNameProperty, value); }
}

Then you could set it from your TabItems:

<local:TaxCodeMappingFooter TabName="FedStateTaxesTab" DataContext="{Binding 
    RelativeSource={RelativeSource AncestorType=UserControl}}" />

And Bind to it from inside your control:

<Button Name="AddButton" Command="{Binding Path=DataContext.AddClickCommand}" 
    CommandParameter="{Binding TabName, RelativeSource={RelativeSource 
    AncestorType=TaxCodeMappingFooter}}" ... />
Sheridan
  • 68,826
  • 24
  • 143
  • 183
0

As others have said, if you model your view model structure appropriately, this would not be much of an issue.

If you really want to bind against an ancestor element, you can use a RelativeSource of FindAncestor, then specify the AncestorType. Note that you may need to tweak AncestorLevel if you are the descendant of more than one TabItem.

{Binding Path=Name
         RelativeSource={RelativeSource Mode=FindAncestor,
                                        AncestorType={x:Type TabItem}}}

(wrapping added for clarity)

Mike Strobel
  • 25,075
  • 57
  • 69