2010-09-20 82 views
0

我在我的項目中有一個自定義ItemsControl,我試圖爲它編寫一個樣式,它將控件本身的一個項目列表與一個Dependency屬性上的項目列表組合在一起。綁定範圍 - 樣式和模板

這裏是我的資源字典中相應的XAML:

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

的想法是,風格上應該結合具有任何元素的靜態元素在每個實例版本的控件上定義。

我的問題是,上面的綁定不起作用(我也意識到了爲什麼!)所以我需要一種方式來綁定到樣式的父級,但由於setter不在視覺/邏輯樹,只是一個屬性我有點困惑如何進行。

回答

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> 

代碼隱藏:

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 
}