Home > Net >  Bind Style-Resource to StackPanel items
Bind Style-Resource to StackPanel items

Time:03-27

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