0

I'm trying to make a TabControl, populated with few UserControls each with a separate ViewModel.

I've declared it in my XAML like this:

<TabControl Margin="10,10,10,40" ItemsSource="{Binding Test}"> <TabControl.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Name}" FontSize="16" Padding="5"/> </DataTemplate> </TabControl.ItemTemplate> </TabControl> 

As you can see I'm trying to obtain the name of the tab through a property located in it's View Model:

public class GeneralTabViewModel : INotifyPropertyChanged { private string _name; public string Name { get { return _name; } set { _name = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler PropertyChanged; public GeneralTabViewModel() { Name = "Name"; } [NotifyPropertyChangedInvocator] protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } 

The View Model associated with the window that holds the TabControl is declared as follows:

public class SettingsViewModel { public ObservableCollection<UserControl> Test { get; set; } public SettingsViewModel() { Test = new ObservableCollection<UserControl> { new GeneralTab(), new GeneralTab() }; } } 

Building the program like this yields an empty Header for the 2 tabs.

How can I bind the TextBlock's Text property to the Name property located in the View Model of the UserControl?

If I change the ItemSource type from ObservableCollection<UserControl> to ObservableCollection<GeneralTabViewModel> I will be able to access the property, but how am I going to visualize the UserControl than?

6
  • Share code of user control. Commented Feb 6, 2018 at 1:14
  • Your GeneralTab User control must implement Generaltabviewmodel. Bind name property there. Commented Feb 6, 2018 at 1:16
  • @GaurangDave Are you implying that my user control should be a view model and a user control at the same time? Commented Feb 6, 2018 at 1:22
  • If I understood correctly then your need is to put your user control in each tab item from Test collection in SettingsViewModel. Your Binding SettingsViewModel in your given xaml code then it can not access property of GeneralTabViewModel. You should put GeneralTab (usercontrol) code here with question. Commented Feb 6, 2018 at 1:35
  • @GaurangDave There's nothing in the UserControl's codebehind. Commented Feb 6, 2018 at 1:36

1 Answer 1

1

It is wrong to have UserControls in your SettingsViewModel. It should instead have a collection of GeneralTabViewModels:

public class SettingsViewModel { public ObservableCollection<GeneralTabViewModel> Test { get; } public SettingsViewModel() { Test = new ObservableCollection<GeneralTabViewModel> { new GeneralTabViewModel { Name = "Tab 1" }, new GeneralTabViewModel { Name = "Tab 2" } }; } } 

You would then use the UserControl in the ItemTemplate of your TabControl:

<TabControl Margin="10,10,10,40" ItemsSource="{Binding Test}"> <TabControl.ItemTemplate> <DataTemplate> <GeneralTab TabName="{Binding Name}"/> </DataTemplate> </TabControl.ItemTemplate> </TabControl> 

In order to make ths work, it is important that GeneralTab does not explicitly set its DataContext property. It may look like this:

<UserControl x:Class="YourNamespace.GeneralTab" ...> <Grid> <TextBlock FontSize="16" Padding="5" Text="{Binding TabName, RelativeSource={RelativeSource AncestorType=UserControl}}"/> </Grid> </UserControl> 

with this dependency property in its code behind:

public static readonly DependencyProperty TabNameProperty = DependencyProperty.Register(nameof(TabName), typeof(string), typeof(GeneralTab)); public string TabName { get { return (string)GetValue(TabNameProperty); } set { SetValue(TabNameProperty, value); } } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.