Aleksei
Aleksei

Reputation: 67

MouseOver trigger doesn`t work after programmatically set Foreground

I'm new to WPF, but searching internet for some days I couldn't figure out my problem.

After I programmatically change Foreground property, IsMouseOver trigger doesn't work. Please be tolerant and thank in advance :)

<Style x:Key="ZizaMenuItem" TargetType="{x:Type Button}">
    <Setter Property="SnapsToDevicePixels" Value="True" />
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="HorizontalContentAlignment" Value="Center"/>
    <Setter Property="Margin" Value="5,0,5,0"/>
    <Setter Property="Height" Value="30"/>
    <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="{x:Type Button}">
        <Label FontSize="14"  Content="{TemplateBinding Content}" Name="ZizaMenuItemText" />
        <ControlTemplate.Triggers>
          <Trigger Property="IsMouseOver" Value="True">
            <Setter TargetName="ZizaMenuItemText" Property="Foreground" Value="#ff0000"/>
          </Trigger>
        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

<StackPanel Height="30" Name="ZizaMenu" Orientation="Horizontal" Margin="0,12,0,0" VerticalAlignment="Top">
  <Label Content="ZIZA" FontSize="11" FontWeight="Bold" Foreground="Black" Height="25" Margin="20,0,10,0" />
  <Button Name="ZizaMenuInteresting" Click="ZizaMenuItemClicked" Content="ИНТЕРЕСНОЕ" Style="{StaticResource ZizaMenuItem}" />
  <Button Name="ZizaMenuBest" Click="ZizaMenuItemClicked" Content="ЛУЧШЕЕ" Style="{StaticResource ZizaMenuItem}" />
  <Button Name="ZizaMenuAuto" Click="ZizaMenuItemClicked" Content="АВТО" Style="{StaticResource ZizaMenuItem}" />
</StackPanel>
private void ZizaMenuItemClicked(object sender, RoutedEventArgs e)
{
    // get label object from template
    Button zizaMenuItem = (Button)sender;
    Label zizaMenuItemText = (Label)zizaMenuItem.Template.FindName("ZizaMenuItemText", zizaMenuItem);
    // set Foreground color for all buttons in menu
    foreach (var item in ZizaMenu.Children)
      if (item is Button)
        ((Label)(item as Button).Template.FindName("ZizaMenuItemText", (item as Button))).Foreground = Brushes.Black;
    // set desired color to clicked button label
    zizaMenuItemText.Foreground = new SolidColorBrush(Color.FromRgb(102, 206, 245));
}

Upvotes: 0

Views: 1498

Answers (2)

brunnerh
brunnerh

Reputation: 185489

That is horrible code, do not mess with controls inside control templates, ever. Template.FindName is something only the control that is being templated should call internally to get its parts, and only those, everything else should be considered uncertain.

If you need to change a property template bind it, and then bind or set said property on the instance. In terms of precedence you need to make sure not to create a local value which overrides the triggers (that is what you did). You can use a Style and Setter on the Label to bind the default Foreground.

<Label.Style>
    <Style TargetType="Label">
        <Setter Property="Foreground" Value="{TemplateBinding Foreground}"/>
    </Style>
</Label.Style>

Now you just need to set the Foreground of the Button itself, the Trigger should still internally have precedence over that Setter.

Upvotes: 2

Alex Gelman
Alex Gelman

Reputation: 534

It has to do with dependency property value precedence. Local values have higher precedence than template triggers.

For more information read this: http://msdn.microsoft.com/en-us/library/ms743230.aspx

Upvotes: 1

Related Questions