如何在Style内部的WPF数据模板中使用绑定

本文关键字:绑定 数据 WPF Style 内部 | 更新日期: 2023-09-27 18:29:22

我是WPF数据绑定/样式/模板的新手。。。我正在尝试使用样式将一组属性值应用于按钮。样式绑定到类的字段。正如您所看到的,这对于BackColor属性非常适用。但是,当我尝试设置TextBlock的Text时,它不起作用(也不会出现绑定错误)。我的最终目标是也能够设置一个图像作为内容。

当我不使用DataTemplate,并使用SetterProperty="Content"而不是"ContentTemplate"时,它将适用于一个按钮,但当添加第二个按钮时,它会给我一个运行时错误"指定的元素已经是另一个元素的逻辑子元素。请先断开它。"

我在这里错过了什么?我在"TextBlock Text="中输入了什么???"

顺便说一句。一旦它工作起来,我想把样式移到全局范围,这样我就不想使用任何明确引用MyClass 的东西

<Window.Resources>
    <Style TargetType="Button" x:Key="MyStyle">
        <Setter Property="Background" Value="{Binding BackColor}"/>
        <Setter Property="ContentTemplate">
            <Setter.Value>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="XYZ-"/>
                        <TextBlock Text="{Binding Text}"/>
                    </StackPanel>                        
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>
<StackPanel Orientation="Horizontal" Height="30">
    <Button Style="{StaticResource MyStyle}" DataContext="{Binding Action1}"/>
    <Button Style="{StaticResource MyStyle}" DataContext="{Binding Action1}"/>
    <Button Style="{StaticResource MyStyle}" DataContext="{Binding Action2}"/>
    <Button Style="{StaticResource MyStyle}" DataContext="{Binding Action2}"/>
</StackPanel>

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
        Action1 = new MyClass() { Text = "ACTION1", BackColor = new SolidColorBrush(Colors.Red) };
        Action2 = new MyClass() { Text = "ACTION2", BackColor = new SolidColorBrush(Colors.Green) };
    }
    public MyClass Action1{get; private set;}
    public MyClass Action2{get; private set;}
}
public class MyClass
{
    public string Text { get; set; }
    public Brush BackColor { get; set; }
}

如何在Style内部的WPF数据模板中使用绑定

在您最初的问题中,您需要

<Setter Property="Background" Value="{Binding BackColor}"/>
<Setter Property="Content" Value="{Binding Text}"/>

现在您需要使用相对源绑定

<TextBlock Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, 
           AncestorType=Button}, Path=DataContext.Text}"/>

然而,您可能会更好地使用ItemsControl,如下

Xaml

<Page.Resources>
    <DataTemplate x:Key="ItemTemplate" DataType="{x:Type Samples:MyClass}">
        <Button Background="{Binding BackColor}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="XYZ-"/>
                <TextBlock Text="{Binding Text}"/>
            </StackPanel>
        </Button>
    </DataTemplate>
  <ItemsPanelTemplate x:Key="ItemsPanelTemplate">
        <StackPanel Orientation="Horizontal"/>
    </ItemsPanelTemplate>
</Page.Resources>
<Page.DataContext>
    <Samples:DataTemplateItemsControlViewModel/>
</Page.DataContext>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <ItemsControl 
        ItemsSource="{Binding Items}" 
        ItemsPanel="{StaticResource ItemsPanelTemplate}"
        ItemTemplate="{StaticResource ItemTemplate}"/>
</Grid>

C#

public class DataTemplateItemsControlViewModel
{
    public DataTemplateItemsControlViewModel()
    {
        Items =
            new Collection<MyClass>
                {
                    new MyClass
                        {
                            Text = "ACTION1", 
                            BackColor = new SolidColorBrush(Colors.Red)
                        },
                    new MyClass
                        {
                            Text = "ACTION2", 
                            BackColor = new SolidColorBrush(Colors.Blue)
                        },
                    new MyClass
                        {
                            Text = "ACTION3", 
                            BackColor = new SolidColorBrush(Colors.Green)
                        },
                    new MyClass
                        {
                            Text = "ACTION4", 
                            BackColor = new SolidColorBrush(Colors.Yellow)
                        },
                };
    }
    public IList<MyClass> Items { get; private set; }
}