Добавьте вкладки в элемент управления вкладками из того же DataTemplate, но они не должны быть связаны друг с другом - PullRequest
0 голосов
/ 01 мая 2020

В моей программе wpf я хотел бы иметь вкладки, которые будут генерироваться из массива или списка. Я хотел бы редактировать файлы с каждой вкладкой. Каждая вкладка будет иметь соответствующую папку с одинаковым именем, поэтому все вкладки должны выглядеть одинаково (именно поэтому я использовал DataTemplates), поскольку все файлы во всех каталогах создаются с одинаковыми именами, но их содержимое отличается. У меня есть код, который генерирует вкладки из массива и добавляет имена к вкладкам.

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>

Но у меня есть 2 проблемы:

  1. Я помещаю текстовое поле в содержимое вкладки, и если я создаю более 1 вкладки, все они разделяют одно и то же содержимое в текстовом поле. , Мне нужно создать отдельный экземпляр для каждой вкладки.
  2. Когда вкладка будет создана, мне нужно будет назначить ей каталог (который я сохранил в строке newLocation), а затем отобразить файл (например, sample.txt) в текстовом поле ( fileTextBox).

1 Ответ

1 голос
/ 02 мая 2020
  1. вы испытываете это поведение, потому что при связывании с помощью ItemsSource все элементы TabControl «оптимизируются» путем совместного использования панели для отображения содержимого (см. Этот вопрос )

  2. Я предлагаю вам использовать интерфейс INotifyPropertyChanged в вашей модели представления и добавить данные файла в TabViewModel (я добавил свойство Location, но вы также можете добавить свойство Content)

    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: обратите внимание на использование UpdateSourceTrigger для обновления viewModel при изменении содержимого текстового поля

<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>

...