2010-09-24 2 views
3

Я хочу создать TabControl с несколькими «статическими» TabItems (явно введенными в XAML) и несколькими динамически добавленными TabItems. Для этого я попытался использовать CompositeCollection в качестве элемента TabControl.ItemSource.Привязки внутри CompositeCollection

код

Пример:

<Window x:Class="WpfApplication1.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525" 
     xmlns:sys="clr-namespace:System;assembly=mscorlib" 
     > 
    <Window.Resources> 
    <x:Array x:Key="SomeTexts" x:Type="sys:String"> 
     <sys:String>Text1</sys:String> 
     <sys:String>Text2</sys:String> 
    </x:Array> 
    </Window.Resources> 

    <TabControl> 
    <TabControl.ItemsSource> 
     <CompositeCollection> 
     <TabItem Header="Test"> 
      <StackPanel> 
      <TextBlock x:Name="MyText" Text="Blah" /> 
      <TextBlock Text="{Binding Text, ElementName=MyText}" /> 
      </StackPanel> 
     </TabItem> 
     <CollectionContainer Collection="{StaticResource SomeTexts}" /> 
     </CompositeCollection> 
    </TabControl.ItemsSource> 
    </TabControl> 
</Window> 

Этот пример один фиксированный элемент вкладки и три «динамических» на вкладке элементы (обратите внимание, что «SomeTexts» представляет собой фиксированный массив здесь просто, чтобы облегчить пример, в реальном коде будет динамичной коллекцией).

Пример работает, за исключением привязки «ElementName», которая не работает. Полагаю, это потому, что CompositeCollection не является Freezable (см. Также Why is CompositeCollection not Freezable?).

У кого-нибудь есть решение?

ответ

1

У меня был похожий сценарий. Чтобы решить эту проблему, я нашел following article.

В этом сообщении объясняется, как создать прокси-объект с возможностью замораживания, с которым можно установить контекст данных. Затем вы добавляете этот прокси-сервер в качестве ресурса, на который можно ссылаться как статический ресурс. Смотрите следующее:

public class BindingProxy : Freezable 
{ 
    public static DependencyProperty DataContextProperty = DependencyProperty.Register(
     "DataContext", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null)); 

    public object DataContext 
    { 
     get { return GetValue(DataContextProperty); } 
     set { SetValue(DataContextProperty, value); } 
    } 

    protected override Freezable CreateInstanceCore() 
    { 
     return new BindingProxy(); 
    } 
} 

Это можно затем использовать в вашем XAML, как это:

<Window x:Class="WpfApplication1.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525" 
     xmlns:y="clr-namespace:Namespace.Of.BindingProxy" 
     xmlns:sys="clr-namespace:System;assembly=mscorlib" 
     > 
    <Window.Resources> 
    <x:Array x:Key="SomeTexts" x:Type="sys:String"> 
     <sys:String>Text1</sys:String> 
     <sys:String>Text2</sys:String> 
    </x:Array> 
    <y:BindingProxy x:Key="Proxy" DataContext="{Binding}" /> 
    </Window.Resources> 

    <TabControl> 
    <TabControl.ItemsSource> 
     <CompositeCollection> 
     <TabItem Header="Test"> 
      <StackPanel> 
      <TextBlock x:Name="MyText" Text="Blah" /> 
      <TextBlock Text="{Binding DataContext.SomeProperty, Source={StaticResource Proxy}}" /> 
      </StackPanel> 
     </TabItem> 
     <CollectionContainer Collection="{StaticResource SomeTexts}" /> 
     </CompositeCollection> 
    </TabControl.ItemsSource> 
    </TabControl> 
</Window> 
Смежные вопросы