Передача значений в Style WPF

427
06 октября 2017, 14:39

Как передать значения их элемента в стиль, который к нему привязан?

У меня имеется стиль, который полностью переделывает стандартную кнопку. Но возникла проблема как передать в стиль надписи, подписи и ToolTip.

Кнопки у меня изначально лежат в ItemsControl, который привязан к коллекции. Поэтому и возникла необходимость передавать значения в стиль, чтобы не писать много лишней разметки для каждой кнопки и иметь всегда возможность просто удалить один элемент из List'a в коде, и не лезть в разметку.

Вот код ItemsControl, который привязан к листу типизированному классом Command. В этом классе предполагаю хранить саму команду для кнопки, название команды для пользователя, иконку и описание для ToolTip

<ItemsControl ItemsSource="{Binding TestList}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Style="{StaticResource ButtonStyleLeft}">
                <Button.Content>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="75"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                    </Grid>
                </Button.Content>
            </Button>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Вот подключенный стиль:

<Style x:Key="ButtonStyleLeft"
       TargetType="{x:Type Button}">
    <Setter Property="OverridesDefaultStyle" Value="True"></Setter>
    <Setter Property="HorizontalAlignment" Value="Stretch"></Setter>
    <Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
    <Setter Property="Margin" Value="0,0,0,2"></Setter>
    <Setter Property="Height" Value="75"></Setter>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border Height="75"
                        HorizontalAlignment="Stretch"
                        Background="#FF646464">
                    <ContentPresenter Content="{TemplateBinding Content}"></ContentPresenter>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Из разметки предварительно выкинул все, что не работало. Пытался в стиле переопределить основные настройки. А потом уже добавить контент и команду в разметке ItemsControl'a. Но пока вышло только добавить команду, с ней проблем нет.

Вопросы:

Как работать с картинкой в коде C#, чтобы потом ее передать в <Image Source="{//сюда//}"/>?
Как передать описание для ToolTip?

Answer 1

Ну вот вам пример с картинкой.

Для начала, чтобы передать картинку, нам нужно какое-то свойство. Можно использовать Tag, но это одноразовое решение, а нам надо много, так что навесим attached property:

static class ButtonExtensions
{
    public static ImageSource GetImage(DependencyObject obj)
    {
        return (ImageSource)obj.GetValue(ImageProperty);
    }
    public static void SetImage(DependencyObject obj, ImageSource value)
    {
        obj.SetValue(ImageProperty, value);
    }
    public static readonly DependencyProperty ImageProperty =
        DependencyProperty.RegisterAttached(
            "Image", typeof(ImageSource), typeof(ButtonExtensions));
}

Далее, наш стиль. Добавим картинку:

<Style TargetType="Button" x:Key="ButtonWithImage">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border Height="75"
                    HorizontalAlignment="Stretch"
                    Background="#FF646464"
                    TextBlock.Foreground="White">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="Auto"/>
                        </Grid.RowDefinitions>
                        <Image Source="{Binding (local:ButtonExtensions.Image),
                                          RelativeSource={RelativeSource TemplatedParent}}"
                               Grid.Row="0"/>
                        <ContentPresenter
                            Content="{TemplateBinding Content}"
                            Grid.Row="1" HorizontalAlignment="Center"/>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

((local:ButtonExtensions.Image) — это синтаксис для привязки к attached property, local — это namespace.)

Используем в коде:

<Button Style="{StaticResource ButtonWithImage}"
        local:ButtonExtensions.Image="diskette.jpg">
    This is button content
</Button>

Получаем:

Всё!

Для случая ItemsControl, у меня работает так:

<ItemsControl ItemsSource="{Binding}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Style="{StaticResource ButtonWithImage}"
                    local:ButtonExtensions.Image="{Binding Image}">
                This is button content
            </Button>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
public class MyVM
{
    public string Image { get; }
    public MyVM(string imagePath) => Image = imagePath;
}
DataContext = new MyVM[] { new MyVM(@"diskette.jpg"), new MyVM(@"diskette.jpg") };
READ ALSO
Проблема с передвижением объекта С#

Проблема с передвижением объекта С#

Здравствуйте! Я только начал разбираться с C#, хочу нарисовать движущийся кругНаписал такие методы:

293
Newtonsoft json

Newtonsoft json

Добрый вечер

374
XML не работает на андроиде

XML не работает на андроиде

Ни XmlDocument, ни HtmlDocument (из библиотеки HtmlAgilityPack) не хотят нормально работать с html страницейВот вам пример:

360
socket соединение

socket соединение

Хочу написать клиент-серверное приложение, клиенту нужно будет передавать данные на протяжении огромного количества времениСервер соответственно...

212