2010-09-20 3 views
0

J'ai un ItemsControl personnalisé dans mon projet et j'essaye d'écrire un style pour cela qui combine une liste statique d'éléments avec une liste d'éléments sur une propriété de dépendance sur le contrôle lui-même .Étendue de la reliure - Styles et modèles

Voici le XAML correspondant dans ma ressource Dictionnaire:

<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> 

Et puis le code correspondant dans mes commandes/windows/whatever:

<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> 

L'idée est que le style doit combiner les les éléments statiques avec tous les éléments définis dans l'édition par instance du contrôle. Mon problème est, la liaison ci-dessus ne fonctionne pas (et j'ai réalisé pourquoi aussi!) J'ai donc besoin d'un moyen de pouvoir lier au parent du style, mais puisque le setter n'est pas dans le visuel/arbre logique, juste une propriété, je suis un peu perplexe sur la façon de procéder.

Répondre

0

Que diriez-vous d'implémenter un IValueConverter qui construit le CompositeCollection correct pour le contrôle derrière les scènes? Voir exemple ci-dessous:

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 
}