2010-09-20 3 views
0

У меня есть свой собственный ItemsControl в моем проекте, и я пытаюсь написать стиль для него, который объединяет статический список элементов со списком элементов в свойстве зависимостей в самом элементе управления ,Binding Scope - Styles & Templates

Вот соответствующий XAML в моем Resource Dictionary:

<x:Array Type="{x:Type System:Object}" x:Key="Static_CloudItems"> 
    <Button>One</Button> 
    <Button>Two</Button> 
    <Button>Three</Button> 
</x:Array> 

<Style TargetType="{x:Type ControlsBase:CloudControl}" x:Key="BasicCloudStyle"> 
    <Setter Property="ItemsSource"> 
     <Setter.Value> 
      <CompositeCollection> 
       <CollectionContainer Collection="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ControlsBase:CloudControl}}, Path=CloudItems}" /> 
       <CollectionContainer Collection="{StaticResource Static_CloudItems}" /> 
      </CompositeCollection> 
     </Setter.Value> 
    </Setter> 
</Style> 

А затем соответствующий код в моем управления/окна/независимо:

<ControlsBase:CloudControl Style="{DynamicResource BasicCloudStyle}"> 
    <ControlsBase:CloudControl.CloudItems> 
     <x:Array Type="{x:Type System:Object}"> 
      <Button>Four</Button> 
      <Button>Five</Button> 
     </x:Array> 
    </ControlsBase:CloudControl.CloudItems> 
</ControlsBase:CloudControl> 

Идея заключается в том, что стиль должен сочетать статические элементы с любыми элементами определены в версии экземпляра элемента управления для каждого экземпляра.

Моя проблема: привязка выше не работает (и я понял, почему тоже!) Поэтому мне нужен способ привязки к родительскому стилю, но поскольку установщик не находится в визуальном/логическое дерево, просто свойство. Я немного озадачен тем, как действовать.

ответ

0

Как насчет внедрения IValueConverter, который строит правильный CompositeCollection для управления за кулисами? Смотрите образец ниже:

XAML:

<Window x:Class="StackOverflow.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:System="clr-namespace:System;assembly=mscorlib" 
     xmlns:local="clr-namespace:StackOverflow" 
     Title="MainWindow" Height="350" Width="525" 
     x:Name="window"> 
    <Window.Resources> 
     <x:Array Type="{x:Type System:Object}" x:Key="Static_CloudItems"> 
      <Button>One</Button> 
      <Button>Two</Button> 
      <Button>Three</Button> 
     </x:Array> 

     <local:MyItemsSourceConverter x:Key="myConverter"/> 
     <Style TargetType="{x:Type local:MyControl}" x:Key="BasicCloudStyle"> 
      <Setter Property="ItemsSource" 
        Value="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource myConverter}}"/> 
     </Style> 
    </Window.Resources> 

    <local:MyControl Style="{StaticResource BasicCloudStyle}" > 
     <local:MyControl.InstanceItems> 
      <System:String>Item1</System:String> 
      <System:String>Item2</System:String> 
      <System:String>Item3</System:String> 
     </local:MyControl.InstanceItems> 
    </local:MyControl> 
</Window> 

Code-Behind:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
    } 
} 

public class MyControl : ListBox 
{ 
    public ObservableCollection<object> InstanceItems 
    { 
     get { return (ObservableCollection<object>)GetValue(InstanceItemsProperty); } 
     set { SetValue(InstanceItemsProperty, value); } 
    } 

    // Using a DependencyProperty as the backing store for InstanceItems. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty InstanceItemsProperty = 
     DependencyProperty.Register("InstanceItems", typeof(ObservableCollection<object>), 
     typeof(MyControl), new UIPropertyMetadata(new ObservableCollection<object>())); 
} 

public class MyItemsSourceConverter : IValueConverter 
{ 
    #region IValueConverter Members 

    public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     MyControl mc = value as MyControl; 
     if (mc != null) 
     { 
      CompositeCollection cc = new CompositeCollection(); 

      CollectionContainer container1 = new CollectionContainer(); 
      BindingOperations.SetBinding(container1, CollectionContainer.CollectionProperty, 
       new Binding() 
       { 
        Source = mc, 
        Path = new PropertyPath("InstanceItems") 
       }); 
      cc.Add(container1); 

      CollectionContainer container2 = new CollectionContainer() 
      { 
       Collection = mc.FindResource("Static_CloudItems") as Array 
      }; 

      cc.Add(container2); 

      return cc; 
     } 
     return null; 
    } 

    public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new System.NotImplementedException(); 
    } 

    #endregion 
}