0

Perhaps I'm missing something obvious, but I can't figure this one out... I have a button style defined in App.xml that presents a "flat" looking button:

<Style x:Key="FlatButton" TargetType="{x:Type Button}">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type Button}">
        <Border x:Name="ButtonBorder" BorderThickness="2" BorderBrush="{DynamicResource color_Logo}" Padding="5,3,5,3" HorizontalAlignment="Stretch" Background="White">
          <TextBlock x:Name="ButtonText" FontSize="12" Foreground="{DynamicResource color_Logo}" HorizontalAlignment="Center" VerticalAlignment="Center"><ContentPresenter /></TextBlock>
        </Border>
        <ControlTemplate.Triggers>
          <Trigger Property="IsMouseOver" Value="True">
            <Setter Property="TextBlock.FontWeight" Value="Bold" />
          </Trigger>
          <Trigger Property="IsEnabled" Value="False">
            <Setter Property="BorderBrush" Value="Gray" TargetName="ButtonBorder" />
            <Setter Property="Foreground" Value="Gray" TargetName="ButtonText" />
          </Trigger>
          <Trigger Property="IsPressed" Value="True">
            <Setter Property="Background" Value="{DynamicResource color_LogoLight}" TargetName="ButtonBorder"/>
          </Trigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>          

Works perfectly fine throughout my app. I now need to create a button with this style but where the content, or caption, of the button changes based on the state of a boolean value in the viewmodel. I've tried several iterations and I either end up with a complaint from the compiler that the style property is already set or I just see the object type name as the caption.

I suppose I could create a text property in the viewmodel that exposes the proper caption, but this seems to violate the separation of concerns in MVVM. While I know it's not an arrest-able offense if I do that, my viewmodel shouldn't care about the way the UI presents something, right? It just exposes the state of the object and the UI makes the decision on how to present it.

Another option is to create two buttons and hide the one that is not appropriate, based on the viewmodel boolean. This seems to conform to the MVVM pattern a bit better but I feel like I should be able to do this with a trigger on a single button.

Is it possible to override part of the style resource?

I'm going with the two-button solution, at the moment, but I'd just like to know what I'm missing.

Thanks.

J

Digital Camel
  • 175
  • 2
  • 14
  • bind the text property of the button to the boolean value in your business data, then use an IValueConverter to hand over the appropriate text. https://www.wpftutorial.net/ValueConverters.html – Bubba Jan 25 '17 at 16:26
  • Your button (and button style) should have no business logic for setting the text dynamically, based of some concern outside of the button. As Bubba said, you can bind the text at the button element, and run it through a converter. That way you can reuse the button style. Such as: `` – Lynn Crumbling Jan 25 '17 at 18:43
  • Thanks for the input, folks... At least I know I wasn't just missing something with the XML. – Digital Camel Jan 25 '17 at 20:24

2 Answers2

0

Is it possible to override part of the style resource?

No. You can indeed base a Style on another Style and override specfic setters but you cannot "override" only a part of a ControlTemplate. Unfortunately you must then (re)define the entire template as a whole:

WPF: Is there a way to override part of a ControlTemplate without redefining the whole style?

Community
  • 1
  • 1
mm8
  • 163,881
  • 10
  • 57
  • 88
0

I suppose I could create a text property in the viewmodel that exposes the proper caption, but this seems to violate the separation of concerns in MVVM.

Well, not at all. The very name View Model implies being a model to the View. Of course it depends on a handful of design choices, but this is not a violation of MVVM, in my opinion.

Besides that, I would go with a DataTrigger (defined in Style.Triggers) where you can set specific, view-only strings given the value of your boolean property.

And, please, don't go with the two-button solution, that is closer to an arrestable offense ;o)

heltonbiker
  • 26,657
  • 28
  • 137
  • 252