将样式资源绑定到 StackPanel 项目

Bind Style-Resource to StackPanel items

我正在尝试将在 UserControl 的本地 ResourceDictionary 中定义的 Style-Resource 绑定到 StackPanel 中的所有项目。
StackPanel 的 ItemSource 绑定到 ViewModel 中的 ObservableCollection<Button>

因此,目的是将样式资源绑定到这些按钮的样式-属性。

以下简化方法会导致此错误:

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>

我也尝试过按照此处的建议使用转换器
Binding for WPF Styles
如下:

...
       <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>
...

这会导致相同的错误:

ArgumentException: Style object is not allowed to affect the Style property of the object to which it applies.


是否有任何其他方法可以将 lcoal Style-Resource 绑定到 Stackpanel-ItemSource 中项目的 Setter-属性?

由于您将按钮直接添加到 ItemsSource 集合,因此将按钮样式分配给 ItemsControl 的 ItemContainerStyle 属性 就足够了:

<ItemsControl ItemsSource="{Binding MyButtons}"
              ItemContainerStyle="{StaticResource StyleStackPanelButton}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

或者,在 StackPanel 资源中声明默认按钮样式 - 不带 x:Key

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