【问题标题】:How to use binding in a WPF DataTemplate that is inside a Style如何在样式内的 WPF DataTemplate 中使用绑定
【发布时间】:2012-04-11 08:53:56
【问题描述】:

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

当我不使用 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; }
}

【问题讨论】:

    标签: c# .net wpf templates binding


    【解决方案1】:

    在你原来的问题中,你需要

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

    【讨论】:

    • 感谢您的回答。是的,这行得通,但是我需要在内容下有更多可见的对象。我编辑了我的代码示例以澄清这一点。
    • 没有。使用相对源绑定产生与我上面的代码相同的结果。当我将样式应用于一个按钮时它可以工作,但是对于多个按钮我仍然遇到相同的异常:“指定的元素已经是另一个元素的逻辑子元素。首先断开它。”
    • 我已经逐字复制了你的代码,并将 DataTemplate 修改为 工作正常。
    • 是的,你是对的。我做了一些其他的修改,把它搞砸了。您的解决方案 100% 有效。谢谢一百万!
    猜你喜欢
    • 1970-01-01
    • 2020-12-15
    • 2017-01-30
    • 2016-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多