开发者

XAML trigger setter and property of UIElementCollection type

My control has property Buttons of type UIElementCollection. Is it possible to modify such property via triggers (specifically DataTrigger)?

I have following code:

<Setter Property="Buttons">
    <Setter.Value>
        <Button>A</Button>
        <Button>B</Button>
    </Setter.Value>
</Setter>

And I get error "The property value is set more than once". Wrapping the buttons in UIElementCollection tag doesn't work (UIElementCollection has no default contructor). If I remove the second button, I g开发者_StackOverflow中文版et exception that the Buttons property is not compatible with type Button.

Thanks for any help


You can use an attached behavior to modify a collection with a setter. Here is a working example based on the Panel.Children property which is also a UIElementCollection:

<Grid>
    <Grid.Resources>
        <Style x:Key="twoButtons" TargetType="Panel">
            <Setter Property="local:SetCollection.Children">
                <Setter.Value>
                    <x:Array Type="UIElement">
                        <Button Content="Button1"/>
                        <Button Content="Button2"/>
                    </x:Array>
                </Setter.Value>
            </Setter>
        </Style>
    </Grid.Resources>
    <StackPanel Style="{StaticResource twoButtons}"/>
</Grid>

And here is the attached property SetCollection.Children:

public static class SetCollection
{
    public static ICollection<UIElement> GetChildren(DependencyObject obj)
    {
        return (ICollection<UIElement>)obj.GetValue(ChildrenProperty);
    }

    public static void SetChildren(DependencyObject obj, ICollection<UIElement> value)
    {
        obj.SetValue(ChildrenProperty, value);
    }

    public static readonly DependencyProperty ChildrenProperty =
        DependencyProperty.RegisterAttached("Children", typeof(ICollection<UIElement>), typeof(SetCollection), new UIPropertyMetadata(OnChildrenPropertyChanged));

    static void OnChildrenPropertyChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        var panel = sender as Panel;
        var children = e.NewValue as ICollection<UIElement>;
        panel.Children.Clear();
        foreach (var child in children) panel.Children.Add(child);
    }
}


Edit: A workaround would be using a converter, define your Buttons in a list in some resources:

    <col:ArrayList x:Key="Buttons">
        <Button>A</Button>
        <Button>B</Button>
    </col:ArrayList>

Namespace: xmlns:col="clr-namespace:System.Collections;assembly=mscorlib"

And use a custom converter in the setter to turn it into a collection:

<Setter Property="Buttons" Value="{Binding Source={StaticResource Buttons}, Converter={StaticResource ListToUIElementCollectionConverter}}"/>

Edit: Getting this to work properly is not a trivial task since the converter needs to know the parent object for the UIElementCollection-constructor.


In the end, I decided to circumvent the issue by modifying (with triggers) individual items of the collection (individual buttons) instead of changing whole collection.

I just hide and show the buttons depending on some conditions.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜