0

In my wpf program i would like to have tabs that would be generated from array or list. I would like to edit files with each tab. Each tab would have corresponding folder with same name, so all tabs should look same (this is why I used DataTemplates), since files in all directories are all generated with same names but their content is different. I have code that generates tabs from array and adds names to tabs.

public class MainWindowViewModel
    {
        public ObservableCollection<TabViewModel> Tabs { get; set; }

        public MainWindowViewModel()
        {
            this.Tabs = new ObservableCollection<TabViewModel>();

            var location = System.AppDomain.CurrentDomain.BaseDirectory.ToString();

            string[] folderList = new string[] { "Folder1", "Folder2" };

            foreach (string folder in folderList)
            {
                this.Tabs.Add(new TabViewModel(folder));

                string newLocation = location + folder + "\\";//i would like to point tab to this directory

            }
        }
    }

    public class TabViewModel
    {
        public string Name { get; set; }

        public TabViewModel(string name)
        {
            this.Name = name;
        }
    }
<TabControl ItemsSource="{Binding Tabs}">
    <TabControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name}" />
        </DataTemplate>
    </TabControl.ItemTemplate>
    <TabControl.ContentTemplate>
        <DataTemplate >
            <TextBox x:Name="fileTextBox"/>
        </DataTemplate>
    </TabControl.ContentTemplate>
</TabControl>

But I have 2 problems:

  1. I put textbox in content of a tab and if I create more than 1 tab they all share same content in textbox. I would need to make separate instance for each tab.
  2. When tab is created I would need to assign directory(which i stored in newLocation string) to it and then display file (e.g. sample.txt) in textbox (fileTextBox).
  • Hi Vito - your code is missing example screenshots. Can you please add the same? Also, some sample of code rendered outside of TabControl may help more. – Sanket Tarun Shah May 01 '20 at 15:12

1 Answers1

1
  1. you're experiencing this behavior because, when binding by ItemsSource, all TabControl items are 'optimized' by sharing a panel to render the content (see this question)

  2. I suggest you use the INotifyPropertyChanged interface in your view model and add the file data in the TabViewModel (I added the Location property but you can also add a Content property)

    public class MainWindowViewModel
    {
    public ObservableCollection<TabViewModel> Tabs { get; set; }
    
    public MainWindowViewModel()
    {
        this.Tabs = new ObservableCollection<TabViewModel>();
    
        var location = System.AppDomain.CurrentDomain.BaseDirectory.ToString();
    
        string[] folderList = new string[] { "Folder1", "Folder2" };
    
        foreach (string folder in folderList)
        {
            string newLocation = location + folder + "\\";//i would like to point tab to this directory
    
            this.Tabs.Add(new TabViewModel(folder, newLocation));
    
        }
    }
    
    public class TabViewModel : INotifyPropertyChanged
    {
    private string _name;
    public string Name
    {
        get { return _name; }
        set
        {
            if (_name == value)
              return;
            _name = value;
            OnPropertyChanged();
        }
    }
    
    private string _location;
    public string Location
    {
        get { return _location; }
        set
        {
            if (_location == value)
              return;
            _location = value;
            OnPropertyChanged();
        }
    }
    
    public TabViewModel(string name, string location)
    {
        this.Name = name;
        this.Location = location;
    }
    
    public event PropertyChangedEventHandler PropertyChanged;
    
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
    }
    

XAML: notice the use of UpdateSourceTrigger to update the viewModel when the textbox content changes

<TabControl  ItemsSource="{Binding Tabs}">
<TabControl.ItemTemplate>
  <DataTemplate>
    <TextBlock Text="{Binding Name}" />
  </DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
  <DataTemplate >
      <TextBox x:Name="fileTextBox" Text="{Binding Location, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
  </DataTemplate>
</TabControl.ContentTemplate>

sim1
  • 722
  • 7
  • 12