从同一个 DataTemplate 向选项卡控件添加选项卡,但它们不应相互连接

Add tabs to tab control from same DataTemplate but they shouldn't be connected to each other

在我的 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>

但是我有两个问题:

  1. 我将文本框放在选项卡的内容中,如果我创建了 1 个以上的选项卡,它们都会在文本框中共享相同的内容。我需要为每个选项卡创建单独的实例。
  2. 创建选项卡后,我需要为其分配目录(存储在 newLocation 字符串中),然后在文本框 (fileTextBox) 中显示文件(例如 sample.txt)。
  1. 您遇到此行为是因为,当通过 ItemsSource 绑定时,所有 TabControl 项都是 'optimized' 通过共享面板来呈现内容(请参阅此 question)

  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>