2016-10-02 3 views
-1

Я хочу создать TabControl, где TabItem будет динамически создаваться во время выполнения. TabItem должен быть связан с ViewModel. Эта модель представления поддерживает интерфейс, который знает, как создать контент внутри TabItem. Таким образом, в основном TabItems может использовать любой элемент управления содержимым, определенный моделью просмотра во время выполнения. Я пробовал разные подходы, используя TabControl.ContentTemplate или ControlTemplate и ItemTemplate, но ни один из них не работает. Похоже, что в шаблоне подход должен знать тип содержимого внутри TabItem во время разработки, чтобы иметь возможность отображать себя. Связывание свойства в связанном контексте данных работает отлично, но Content Control не отображается. Можем ли мы просто вывести новый класс MyTabItem: TabItem и создать пользовательский контент и связать его с содержимым MyTabItem. Необходим любой общий подход, который может позволить модели представления создавать содержимое TabItems.WPF TabControl с поддержкой ViewModel Создание содержимого TabItem

+0

ok .. Я мог бы получить свой CustomTabItem: TabItem и создать его содержимое в конструкторе, пройдя в модели представления. ViewModel создает элемент контента и назначает его содержимому tabitem. каковы плюсы и минусы такого подхода. Я не вижу ответов на этот подход в stackoverflow. Разрешение viewModel для создания содержимого tabItems кажется очень стандартной проблемой. –

ответ

0

Вы можете указать DataTemplate для каждого типа, который может быть динамически добавлен в ваш TabControl? Если это так, для вас что-то вроде этой работы?

(Обратите внимание, что TabControl находит то же DataTemplate для обоих ItemTemplate (шаблон заголовка вкладки) и ContentTemplate (отображаемого внутри содержимого вкладки шаблона). Это происходит потому, что мы не указали ни, поэтому WPF просто поднимается по дереву и находит тот же шаблон для обоих из нашего Grid.Resources. Если вы хотите использовать другой шаблон для каждого, вы можете явно указать шаблон, который будет использоваться для ItemTemplate, если это работает для вас, или используйте DataTemplateSelector или аналогичные.)

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="*"/> 
    </Grid.RowDefinitions> 

    <Grid.Resources> 
     <DataTemplate DataType="{x:Type local:DescribableOne}"> 
      <Grid Background="Red"> 
       <TextBlock Text="{Binding Description}" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center"/> 
      </Grid> 
     </DataTemplate> 
     <DataTemplate DataType="{x:Type local:DescribableTwo}"> 
      <Grid Background="Blue"> 
       <TextBlock Text="{Binding Description}" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center"/> 
      </Grid> 
     </DataTemplate> 
     <DataTemplate DataType="{x:Type local:DescribableThree}"> 
      <Grid Background="Green"> 
       <TextBlock Text="{Binding Description}" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center"/> 
      </Grid> 
     </DataTemplate> 
    </Grid.Resources> 

    <StackPanel Orientation="Horizontal"> 
     <Button Command="{Binding AddOne}">Add One</Button> 
     <Button Command="{Binding AddTwo}">Add Two</Button> 
     <Button Command="{Binding AddThree}">Add Three</Button> 
    </StackPanel> 

    <TabControl Grid.Row="1" ItemsSource="{Binding DynamicallyGeneratedTabs}"/> 

</Grid> 

И вид модель:

public class TabControlViewModel 
{ 
    public TabControlViewModel() 
    { 
     AddOne = new RelayCommand(DoAddOne); 
     AddTwo = new RelayCommand(DoAddTwo); 
     AddThree = new RelayCommand(DoAddThree); 
     DynamicallyGeneratedTabs = new ObservableCollection<IDescribable>(); 
    } 

    public ICommand AddOne { get; } 
    public ICommand AddTwo { get; } 
    public ICommand AddThree { get; } 

    public ObservableCollection<IDescribable> DynamicallyGeneratedTabs { get; } 

    private void DoAddOne() 
    { 
     DynamicallyGeneratedTabs.Add(new DescribableOne()); 
    } 

    private void DoAddTwo() 
    { 
     DynamicallyGeneratedTabs.Add(new DescribableTwo()); 
    } 

    private void DoAddThree() 
    { 
     DynamicallyGeneratedTabs.Add(new DescribableThree()); 
    } 
} 

public interface IDescribable 
{ 
    string Description { get; } 
} 

public class DescribableOne : IDescribable 
{ 
    public DescribableOne() 
    { 
     Description = "One"; 
    } 

    public string Description { get; } 
} 

public class DescribableTwo : IDescribable 
{ 
    public DescribableTwo() 
    { 
     Description = "Two"; 
    } 

    public string Description { get; } 
} 

public class DescribableThree : IDescribable 
{ 
    public DescribableThree() 
    { 
     Description = "Three"; 
    } 

    public string Description { get; } 
} 
+0

Спасибо @simon за ответ. В примере, который вы опубликовали, мы знаем тип содержимого в шаблоне данных во время разработки (TextBlock). Где я не Типа. Ok, чтобы быть более конкретным, мои элементы табуляции должны отображать графики и некоторые другие субконтроллеры, такие как таблица. Однако я не знаю, сколько графиков будет отображаться во время разработки, это зависит от ViewModel. Я хочу указать ContentControl вместо TextBlock, но я думаю, что это не сработает. например,