2013-08-28 2 views
4

В моем проекте WPF много кнопок изображения, но так как я не нашел способ сделать это правильно (мне приходится каждый раз писать те же триггеры и стиль, только разница - источник изображения), мой словарь ресурсов стал очень долго. Есть ли лучший способ сделать это?WPF: Повторно используемый шаблон для кнопок изображения?

Вот образец стиля я использую для моих кнопок:

<Style x:Key="ButtonStyle" TargetType="{x:Type Button}"> 
    <!-- Some setters --> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type Button}"> 
       <Grid> 
        <Image Source="Images.png" Stretch="Fill"/> 
       </Grid> 
       <ControlTemplate.Triggers> 
        <!-- Some triggers (IsFocused, IsMouseOver, etc.) --> 
       </ControlTemplate.Triggers> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

Спасибо :)

ответ

9

Самый простой способ создать определенный элемент управления с Image свойством:

public class ImageButton : Button 
{ 
    static ImageButton() 
    { 
     DefaultStyleKeyProperty.OverrideMetadata(typeof (ImageButton), 
      new FrameworkPropertyMetadata(typeof (ImageButton))); 
    } 


    public ImageSource Image 
    { 
     get { return (ImageSource)GetValue(ImageProperty); } 
     set { SetValue(ImageProperty, value); } 
    } 

    public static readonly DependencyProperty ImageProperty = 
     DependencyProperty.Register("Image", typeof(ImageSource), typeof(ImageButton), new PropertyMetadata(default(ImageSource))); 

} 

Тогда вы просто создать стиль для него в Generic.xaml, и связываться с Image собственности вместо установки изображения в явном виде :

<Style x:Key="{x:Type my:ImageButton}" TargetType="{x:Type my:ImageButton}"> 
    <!-- Some setters --> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type my:ImageButton}"> 
       <Grid> 
        <Image Source="{TemplateBinding Image}" Stretch="Fill"/> 
       </Grid> 
       <ControlTemplate.Triggers> 
        <!-- Some triggers (IsFocused, IsMouseOver, etc.) --> 
       </ControlTemplate.Triggers> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

Тогда вы можете просто использовать его как это:

<my:ImageButton Image="Image.png" /> 

Если вам нужно больше изображений для разных состояний кнопки, вы можете добавить дополнительные элементы зависимостей в элемент управления.

Другим возможным подходом является использование того, что я называю «параметризованным стилем», чтобы избежать создания определенного элемента управления; см. this blog post для деталей.

+0

Спасибо, именно то, что мне нужно! – Shugah

+0

В этом примере показана одна серьезная проблема с пользовательскими элементами управления в WPF. Как только я переоцениваю ControlTemplate, вся тематика в основном сломана. Как я могу сохранить все темы исходной кнопки во всех средах? Конечно, я могу скопировать исходный элемент ControlTemplate Button в свой ImageButton, но это будет работать только для общей темы. Я должен был бы предоставить шаблоны управления для всех тем, которые я хочу поддержать. Но это ломается, если есть тема, которую я не знал. – bitbonk

+0

@bitbonk, да, это один из главных недостатков этой системы шаблонов ... К сожалению, я не знаю ни одного хорошего решения. –

0

Вы можете использовать BasedOn атрибута, как это:

<Style x:Key="BlueHighlightedButtonStyle" BasedOn="{StaticResource ButtonStyle}" TargetType="Button"> 
    <Setter Property="Background" Value="DeepSkyBlue"/> 
</Style> 

Это создаст стиль Button с теми же атрибутами, что и ButtonStyle, но с фоном DeepSkyBlue.

+0

Проблема только в том, что атрибут BaseOn не работает со всеми триггерами, я хочу избежать переопределения их каждый раз, когда добавляю другую кнопку. Я попытался использовать TemplateBinding в ControlTemplate, но это не сработало. – Shugah

1

Вы можете попытаться создать настраиваемый элемент управления, который наследует от Button, и использовать его как TargetType в вашем шаблоне. Затем вы можете использовать TemplateBinding в источнике изображения.

<Image Source="{TemplateBinding ImageSource}" Stretch="Fill"/> 

Вам нужно будет создать свойство ImageSource в своем пользовательском элементе управления. Таким образом, вы можете установить источник в xaml, но вам нужен только один шаблон ресурса.