WPF Button IsEnabled Based on ComboBox Selection Overwriting default style

Nate picture Nate · Dec 16, 2008 · Viewed 28.4k times · Source

I have a Button that is looking at 2 comboboxes to make sure they have a value before it is enabled. The problem is the way I am doing it is overwriting the default style declared in my theme project.

<Button x:Name="btnOK" VerticalAlignment="Center" Content="OK" IsDefault="True"  Margin="0" Click="btnOK_Click">
                    <Button.Style>
                      <Style BasedOn="{StaticResource DefaultButton}">
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding ElementName=ddlWageTypes, Path=SelectedItem}" Value="{x:Null}">
                                    <Setter Property="Button.IsEnabled" Value="false"/>
                                </DataTrigger>
                                <DataTrigger Binding="{Binding ElementName=ddlJobTitles, Path=SelectedItem}" Value="{x:Null}">
                                    <Setter Property="Button.IsEnabled" Value="false"/>
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </Button.Style>
                </Button>

I've tried adding BasedOn="{StaticResouce MyDefaultButtonStyleName}" to the style tag but it blows up at runtime.

The error is "'System.Windows.Style' value cannot be assigned to property 'Style' of object 'System.Windows.Controls.Button'. Can only base on a Style with target type that is base type 'IFrameworkInputElement'. Error at object 'System.Windows.Style' in markup file"

Is there a was to do this in XAML without overwriting default style.

EDIT: Code Sample Updated. I get an error on OKButtonStyle saying "Cannot add element to property 'Resources', because the property can have only one child element if it uses an explicit collection tag. Error at object 'System.Windows.Style' in markup file "

<UserControl x:Class="UK.Budgeting.XBAP.ShiftDiff.NewFTEPremiumPaySummary"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:compModel="clr-namespace:System.ComponentModel;assembly=WindowsBase"
    xmlns:local="clr-namespace:UK.Budgeting.XBAP.ShiftDiff">
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="CellTemplates.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>

      <Style TargetType="{x:Type Button}" x:Key="OKButtonStyle" BasedOn="{StaticResource DefaultButton}">
        <Style.Triggers>
          <DataTrigger Binding="{Binding ElementName=ddlWageTypes, Path=SelectedItem}" Value="{x:Null}">
            <Setter Property="Button.IsEnabled" Value="false"/>
          </DataTrigger>
          <DataTrigger Binding="{Binding ElementName=ddlJobTitles, Path=SelectedItem}" Value="{x:Null}">
            <Setter Property="Button.IsEnabled" Value="false"/>
          </DataTrigger>
        </Style.Triggers>
      </Style>

    </UserControl.Resources>
    <Grid>
        <Rectangle Style="{StaticResource DialogRectangle}"/>
        <Border Style="{StaticResource DialogBorder}">
            <Grid HorizontalAlignment="Center" VerticalAlignment="Center" Background="White">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition Width="5"/>
                    <ColumnDefinition MinWidth="300"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition Height="2"/>
                    <RowDefinition/>
                    <RowDefinition Height="2"/>
                    <RowDefinition/>
                    <RowDefinition Height="2"/>
                    <RowDefinition/>
                </Grid.RowDefinitions>

                <TextBlock Grid.Column="0" Grid.Row="0" Style="{StaticResource LabelStyle}">Wage Type</TextBlock>
                <TextBlock Grid.Column="0" Grid.Row="2" Style="{StaticResource LabelStyle}">Job Title</TextBlock>

                <ComboBox x:Name="ddlWageTypes" VerticalAlignment="Top" Grid.Column="2" Grid.Row="0"
                          DisplayMemberPath="DisplayName"
                          SelectedValuePath="WageTypeCode"/>
                <ComboBox x:Name="ddlJobTitles" VerticalAlignment="Top" Grid.Column="2" Grid.Row="2"
                          DisplayMemberPath="JobTitle"
                          SelectedValuePath="JobCode"/>

                <StackPanel Grid.Column="2" Grid.Row="6" VerticalAlignment="Top" Orientation="Horizontal" Margin="5">
                  <Button x:Name="btnOK" VerticalAlignment="Center" Content="OK" IsDefault="True"  Margin="0" Click="btnOK_Click" Style="{StaticResource OKButtonStyle}"/>
                    <Button x:Name="btnCancel" VerticalAlignment="Center" Content="Cancel" IsCancel="True" Margin="10,0,0,0" Click="btnCancel_Click"/>
                </StackPanel>
            </Grid>
        </Border>
    </Grid>
</UserControl>

Answer

Szymon Rozga picture Szymon Rozga · Dec 16, 2008

How is this

BasedOn="{StaticResouce DefaultButton}"

supposed to refer to the default button style? This crashes because DefaultButton is an undefined resource in your app.

It should be:

BasedOn="{StaticResource {x:Type Button}}"

EDIT: Sorry, answered too hastily.

I noticed now your button has a Style={} set, and is pointing to a style called OkBUttonStyle. This is the style that should define everything and be based on the default button style. By everything, I include those triggers. What you are saying in the XAML is that Style is the Content of your Button.

Maybe some code will help:

 <Window x:Class="WindowsApplication7.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="WindowsApplication7" Height="300" Width="300"
    >
  <Window.Resources>
    <Style TargetType="{x:Type Button}" x:Key="defaultButtonStyle">
      <Setter Property="Background" Value="Red" />
    </Style>

    <Style TargetType="{x:Type Button}" x:Key="okButtonStyle" BasedOn="{StaticResource defaultButtonStyle}">
      <Setter Property="Foreground" Value="Green" />
      <Style.Triggers>
        <Trigger Property="IsEnabled" Value="True">
          <Setter Property="Background" Value="Yellow" />
        </Trigger>
        <Trigger Property="IsEnabled" Value="False">
          <Setter Property="Foreground" Value="Blue" />
        </Trigger>
      </Style.Triggers>
    </Style>
  </Window.Resources>
  <StackPanel>
    <Button>System default</Button>
    <Button Style="{StaticResource defaultButtonStyle}">My Default</Button>
    <Button Style="{StaticResource okButtonStyle}">Ok</Button>
    <Button Style="{StaticResource okButtonStyle}" IsEnabled="False">Ok disabled</Button>
  </StackPanel>
</Window>