I am trying to bind a a Style-Resource which is defined in the local ResourceDictionary of a UserControl to all items in a StackPanel.
The ItemSource of the StackPanel is bound to an ObservableCollection<Button>
in the ViewModel.
Thus, the aim is to bind the Style-Resource to the Style-Property of these Buttons.
The following simplified approach results in this error:
ArgumentException: Style object is not allowed to affect the Style property of the object to which it applies.
MyViewModel.cs:
public class MyViewModel
{
public ObservableCollection<Button> MyButtons { get; private set; }
}
MyView.xaml
<UserControl x:Class="MyView"
d:DataContext="{d:DesignInstance Type=MyViewModel}">
<UserControl.Resources>
<ResourceDictionary>
<Style x:Key="StyleStackPanelButton" TargetType="{x:Type Button}"
BasedOn="{StaticResource MyDefaultStyle}">
<Setter Property="Margin" Value="15" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</ResourceDictionary>
</UserControl.Resources>
<StackPanel>
<ItemsControl ItemsSource="{Binding MyButtons}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal">
<StackPanel.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Style" Value="{StaticResource StyleStackPanelButton}" />
</Style>
</StackPanel.Resources>
</StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<Button Style="{StaticResource StyleStackPanelButton}" />
</StackPanel>
</UserControl>
I've also tried to use a Converter as suggested here
Binding for WPF Styles
as follows:
...
<ItemsControl ItemsSource="{Binding ButtonExtensions}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal">
<StackPanel.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Style">
<Setter.Value>
<MultiBinding Converter="{StaticResource StyleConverter}">
<MultiBinding.Bindings>
<Binding RelativeSource="{RelativeSource Self}" />
<Binding Source="{StaticResource StyleStackPanelButton}" />
</MultiBinding.Bindings>
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</StackPanel.Resources>
</StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
...
This results in the same error:
ArgumentException: Style object is not allowed to affect the Style property of the object to which it applies.
Is there a any other way to bind a lcoal Style-Resource to a Setter-Property of an Item in a Stackpanel-ItemSource?
CodePudding user response:
Since you are adding Buttons directly to the ItemsSource collection, it is sufficient to assign the Button Style to the ItemContainerStyle
property of the ItemsControl:
<ItemsControl ItemsSource="{Binding MyButtons}"
ItemContainerStyle="{StaticResource StyleStackPanelButton}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Alternatively, declare a default Button Style - without x:Key
- in the StackPanel Resources:
<ItemsControl ItemsSource="{Binding MyButtons}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal">
<StackPanel.Resources>
<Style TargetType="Button"
BasedOn="{StaticResource StyleStackPanelButton}"/>
</StackPanel.Resources>
</StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>