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.
精彩评论