WPF: TabControl и динамические элементы TabItem

Я пытаюсь создать графический интерфейс для моего текущего проекта, используя WPF на С#. Я хотел бы иметь вкладки (динамически создаваемые во время выполнения), и каждая вкладка должна открывать таблицу с одинаковыми заголовками столбцов, но разным содержимым.

Я знаю, что мог бы реализовать такие вкладки и таблицы:

<Grid>
    <TabControl  x:Name="tabControl"  TabStripPlacement="Left">
        <TabItem Header="Example 1" x:Name="tabItem" >
            <DataGrid ItemsSource="{Binding TagCollection.Tags}" AutoGenerateColumns="False">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Tag" Binding="{Binding Tag}" />
                    <DataGridTextColumn Header="Description" Binding="{Binding Description}" />
                    <DataGridTextColumn Header="Value" Binding="{Binding Value}" />                                              
                </DataGrid.Columns>
            </DataGrid>
        </TabItem>
        <TabItem Header="Example 2" x:Name="tabItem1" >
            <DataGrid ItemsSource="{Binding TagCollection.Tags}" AutoGenerateColumns="False">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Tag" Binding="{Binding Tag}" />
                    <DataGridTextColumn Header="Description" Binding="{Binding Description}" />
                    <DataGridTextColumn Header="Value" Binding="{Binding Value}" />
                </DataGrid.Columns>
            </DataGrid>
        </TabItem>

    </TabControl>

</Grid>

Как я могу создать такое представление с помощью кода? Я еще не привык к привязкам и подобным вещам, поэтому, возможно, кто-нибудь может показать мне короткий пример?

Спасибо, Катзе.


person Kat Ze    schedule 22.09.2015    source источник
comment
Погуглите MVVM TabControl... это должно помочь вам в работе. MVVM сделает это очень легко, как только вы начнете.   -  person KornMuffin    schedule 22.09.2015


Ответы (3)


Я создал пример проекта DynamicTabs. Некоторый пример контекста в конструкторе:

var tabs = new ObservableCollection<MyTab>();
int tabsCount = 5;
for (var i = 1; i <= tabsCount; i++)
{
    var tab = new MyTab() {Header = "Tab " + i};
    tab.Data.Add(new MyTabData() {Column1 = "col1" + i, Column2 = "col2" + i, Column3 = "col3" + i});
    tabs.Add(tab);
}
DataContext = tabs;

Классы для примера контекста:

public class MyTab
{
    public string Header { get; set; }

    public ObservableCollection<MyTabData> Data { get; } = new ObservableCollection<MyTabData>();
}

public class MyTabData
{
    public string Column1 { get; set; }
    public string Column2 { get; set; }
    public string Column3 { get; set; }
}

И XAML:

<Window x:Class="DynamicTabs.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:DynamicTabs"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<TabControl ItemsSource="{Binding}">
    <TabControl.ItemTemplate>
        <DataTemplate DataType="local:MyTab">
            <TextBlock Text="{Binding Header}"/>
        </DataTemplate>
    </TabControl.ItemTemplate>
    <TabControl.ContentTemplate>
        <DataTemplate DataType="local:MyTab">
            <DataGrid ItemsSource="{Binding Data}">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Column 1" Binding="{Binding Column1}" />
                    <DataGridTextColumn Header="Column 2" Binding="{Binding Column2}" />
                    <DataGridTextColumn Header="Column 3" Binding="{Binding Column3}" />
                </DataGrid.Columns>
            </DataGrid>
        </DataTemplate>
    </TabControl.ContentTemplate>
</TabControl>

ItemTemplate is for Header part of TabPage and ContentTemplate for Content of each TabPage.

person Spawn    schedule 22.09.2015
comment
спасибо, это работает хорошо! единственная проблема, которая осталась, это то, что теперь все столбцы создаются 2 раза. Первый с именами заголовков и второй с именами привязки - person Kat Ze; 22.09.2015
comment
@Kat Ze, используйте свойство AutoGenerateColumns=False - person Spawn; 22.09.2015


С некоторыми незначительными обновлениями кода программной части вы сможете сделать это с помощью:

<TabControl  x:Name="tabControl"  TabStripPlacement="Left" ItemsSource="{Binding Path=TableCollection}">
    <TabControl.ItemTemplate>
        <DataTemplate DataType="{x:Type YourTableType}">
          <TabItem Header={Binding TableName}>
            <DataGrid ItemsSource="{Binding Rows}" AutoGenerateColumns="False">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Tag" Binding="{Binding Tag}" />
                    <DataGridTextColumn Header="Description" Binding="{Binding Description}" />
                    <DataGridTextColumn Header="Value" Binding="{Binding Value}" />
                </DataGrid.Columns>
            </DataGrid>
          </TabItem>
        </DataTemplate>
    </TabControl.ItemTemplate>
</TabControl>

Просто замените свойства в привязках в соответствии с вашими потребностями.

person xum59    schedule 22.09.2015