从同一个 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 个以上的选项卡,它们都会在文本框中共享相同的内容。我需要为每个选项卡创建单独的实例。
- 创建选项卡后,我需要为其分配目录(存储在 newLocation 字符串中),然后在文本框 (fileTextBox) 中显示文件(例如 sample.txt)。
您遇到此行为是因为,当通过 ItemsSource
绑定时,所有 TabControl 项都是 'optimized' 通过共享面板来呈现内容(请参阅此 question)
我建议您在视图模型中使用 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>
在我的 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 个以上的选项卡,它们都会在文本框中共享相同的内容。我需要为每个选项卡创建单独的实例。
- 创建选项卡后,我需要为其分配目录(存储在 newLocation 字符串中),然后在文本框 (fileTextBox) 中显示文件(例如 sample.txt)。
您遇到此行为是因为,当通过
ItemsSource
绑定时,所有 TabControl 项都是 'optimized' 通过共享面板来呈现内容(请参阅此 question)我建议您在视图模型中使用 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>