Как использовать привязку в шаблоне данных WPF, который находится внутри стиля - PullRequest
1 голос
/ 27 марта 2012

Я новичок в привязке данных / стиле / шаблонах WPF ... Я пытаюсь применить набор значений свойств к кнопкам с помощью стиля.Стиль привязывается к полям класса.Как видите, это прекрасно работает для свойства BackColor.Но когда я пытаюсь установить текст TextBlock, он не работает (и при этом я не получаю ошибку привязки).Моя конечная цель также заключается в том, чтобы иметь возможность установить изображение в качестве содержимого.

Когда я не использую DataTemplate и использую SetterProperty = "Content" вместо "ContentTemplate", он будет работать для одной кнопки,но при добавлении второй кнопки возникает ошибка во время выполнения: «указанный элемент уже является логическим дочерним элементом другого элемента. Сначала отключите его».

Что мне здесь не хватает?Что я помещаю в "TextBlock Text =" ??? "

btw. Я хотел бы переместить стиль в глобальную область, как только он заработает, поэтому я не хочу использовать ничего, что явно ссылается на 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; }
}

1 Ответ

5 голосов
/ 27 марта 2012

В исходном вопросе вам нужно было

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