我认为我正在寻找的是MVVM,但我看过的例子并没有帮助,所以基于我的问题的例子应该有所帮助。我已经在TabControl中有内容,所以我无法使用Items collection must be empty before using ItemsSource.
,因为它会抛出异常;
TabControl.Items.Add(newTabItem)
...使用DataTemplate
可能需要更多工作,因为必须关闭某些标签页。
我有一个TabControl,其中第一个选项卡包含一个包含人员列表的DataGrid,我希望每当在DataGrid中单击一个项目时,都会创建一个包含该人员详细信息的新选项卡。我想将person对象传递给TabItem&#34; scope / class&#34;并应显示该人的内容。我为人员详细信息TabItem创建了一个<TabControl Name="AttorneysTabControl" Grid.Column="2" Grid.Row="0">
<TabControl.Resources>
<DataTemplate x:Key="AttorneyTabHeader">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Attorney.Names}" Margin="2,0,0,0" FontSize="16" VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="AttorneyTabContent">
<StackPanel>
<TextBlock Text="{Binding Attorney.Names}" />
<TextBlock Text="{Binding Attorney.Age}"/>
<ToolBar>
<Button ToolTip="">Delete</Button>
<Button ToolTip="">Edit</Button>
</ToolBar>
</StackPanel>
</DataTemplate>
</TabControl.Resources>
<TabItem>
<TabItem.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Attorneys" Margin="2,0,0,0" FontSize="16" VerticalAlignment="Center" />
</StackPanel>
</TabItem.Header>
<TabItem.Content>
<Grid Background="#FFE5E5E5" Height="Auto">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="5" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
...
</Grid>
</TabItem.Content>
</TabItem>
<!-- This part here -->
<!-- I want this to repeat. I think I should use a UserControl for this since I want the content to have it's own class -->
<TabItem ContentTemplate="{StaticResource AttorneyTabContent}" HeaderTemplate="{StaticResource AttorneyTabHeader}" />
</TabControl>
,您可以在下面看到它;
private List<Record> allItems; // with getter and setter
private List<Record> selectedItems; // with getter and setter
public void onSelect(SelectEvent event) {
if (null == event || null == event.getObject()) {
return;
}
if (!event.isCtrlKey()) {
setSelectedItems(new ArrayList<Record>());
}
Record item = (Record)event.getObject();
if (!getSelectedItems().contains(item)) {
getSelectedItems().add(item);
}
}
public void onUnselect(UnselectEvent event) {
if (null == event || null == event.getObject()) {
return;
}
Record item = (Record)event.getObject();
if (getSelectedItems().contains(item)) {
getSelectedItems().remove(item);
}
}
public void deleteSelected() {
if (getAllItems().isEmpty()) {
addErrorMessage("listEmpty");
return;
}
if (getSelectedItems().isEmpty()) {
addErrorMessage("noItemSelected");
return;
}
for (Record item : getSelectedItems()) {
if (getAllItems().contains(item)) {
getAllItems().remove(item);
}
}
}
答案 0 :(得分:0)
除非我遗漏了你的要求,否则这不是不可能的。我会说它听起来不是一个好的用户体验,但你比我更了解你的用户和用例。
我把我认为会做你想做的事情放在一起。您需要根据数据进行调整。我希望无论如何都有帮助。请记住,这只是概念代码的证明。
首先是MainWindow
的XAML。这里没什么特别的。它最初是一个简单的TabControl
托管TabItem
Listbox
。
<Window x:Class="WpfTabControl1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfTabControl1"
mc:Ignorable="d"
Title="TabControl Sample" Height="350" Width="525">
<Window.Resources>
<x:Array x:Key="Items" Type="{x:Type local:Item}">
<local:Item Name="Item A" Value="1" />
<local:Item Name="Item B" Value="2" />
<local:Item Name="Item C" Value="3" />
</x:Array>
</Window.Resources>
<Grid>
<TabControl x:Name="ItemTabControl">
<TabItem Header="Items">
<ListBox x:Name="ItemListBox" ItemsSource="{StaticResource Items}"
SelectionChanged="ListBox_SelectionChanged" />
</TabItem>
</TabControl>
</Grid>
</Window>
背后的代码是大多数有趣的事情发生的地方。我根据项目的选项卡是否已存在,在事件处理程序中执行以下两项操作之一 - 我创建选项卡或选择选项卡。
public partial class MainWindow : Window
{
public MainWindow() => InitializeComponent();
void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (ItemListBox.SelectedItem is Item item) {
// select the tab if one was already created for the item;
// otherwise, create a new tab for it
if (TabExists(item.Name, out TabItem tab)) {
ItemTabControl.SelectedItem = tab;
}
else {
var newItem = new ItemTabItem() {
Item = (Item)ItemListBox.SelectedItem
};
int newIndex = ItemTabControl.Items.Add(newItem);
ItemTabControl.SelectedIndex = newIndex;
}
}
}
bool TabExists(string name, out TabItem tab)
{
tab = (from object item in ItemTabControl.Items
let t = item as ItemTabItem
where t != null && t.Item.Name == name
select t).FirstOrDefault();
return (tab != null);
}
}
我的ItemTabItem
(我知道名字很棒)负责显示Item
类实例。这是XAML,后面跟着代码。
<TabItem x:Class="WpfTabControl1.ItemTabItem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfTabControl1"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Text="Name" />
<TextBlock Grid.Row="1" Text="Value" />
<TextBox Grid.Column="1" Text="{Binding Name, Mode=TwoWay}" />
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Value, Mode=TwoWay}" />
</Grid>
</TabItem>
现在代码背后。我们可以直接设置DataContext
,但属性使它更清晰,并允许我设置标题(可能数据绑定它)。
public partial class ItemTabItem : TabItem
{
private Item item;
public ItemTabItem() => InitializeComponent();
public Item Item
{
get => item;
set
{
item = value;
DataContext = value;
Header = item?.Name;
}
}
}
Item
类并不特别。
public class Item
{
public string Name { get; set; }
public int Value { get; set; }
public override string ToString() => Name;
}