代码之家  ›  专栏  ›  技术社区  ›  Aren

绑定范围-样式和模板

  •  0
  • Aren  · 技术社区  · 15 年前

    我有个习惯 ItemsControl 在我的项目中,我尝试为它编写一种样式,它将静态的项列表与控件本身的依赖属性上的项列表相结合。

    以下是我的资源字典中的相应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>
    

    然后是我的控件/windows/中的相应代码:

    <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不在视觉/逻辑树中,所以它只是一个属性,我对如何继续有点困惑。

    1 回复  |  直到 15 年前
        1
  •  0
  •   ASanch    15 年前

    如何实现一个为幕后控制构建正确的复合集合的ivalueConverter?见下面的示例:

    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
    }