Свойство триггера wpf IsPressed не работает правильно

Когда я нажимаю Button, изображение в нем должно измениться и оставаться измененным. Я пытался использовать Triggers на ButtonStyle, привязав изображение к IsPressed собственность, но когда Button отпускается, изображение возвращает предыдущее. Пожалуйста помоги.

<Button Content="Easy Locate" Height="20" Width="85" Margin="0,2,0,0">
  <Button.Style>
    <Style TargetType="{x:Type Button}">
      <Style.Triggers>
        <Trigger Property="IsPressed" Value="True">
          <Setter Property="Template">
            <Setter.Value>
              <ControlTemplate TargetType="{x:Type Button}">
                <Border BorderThickness="0">
                  <Image Source="/AltusClient;component/Images/waiting.png"
                         Height="20"
                         Width="25"/>
                </Border>
                <!--<ControlTemplate.Triggers>
                  <Trigger Property="IsPressed" Value="True">
                    <Setter Property="Background" Value="Transparent"/>
                    <Setter Property="BorderThickness" Value="0"/>
                  </Trigger>
                </ControlTemplate.Triggers>-->
              </ControlTemplate>
            </Setter.Value>
          </Setter>
        </Trigger>
      </Style.Triggers>
    </Style>
  </Button.Style>
</Button>

2 ответа

Решение

Вот пример кнопки, которая работает так, как вы хотите. Вы можете легко переключить кнопку обратно в ее состояние по умолчанию, добавив еще один Trigger установить его Tag собственность на null, пустая строка или что-то еще в мире, кроме "ButtonHasBeenPressed",

<Button Content="Button Content">
    <Button.Style>
        <Style TargetType="Button">
            <Style.Resources>
                <ControlTemplate 
                    x:Key="PressedTemplate" 
                    TargetType="Button">
                    <Border 
                        Background="LightSkyBlue" 
                        BorderBrush="DeepSkyBlue" 
                        BorderThickness="4"
                        >
                        <TextBlock 
                            Text="Replace this TextBlock with your own content" 
                            Foreground="ForestGreen" 
                            />
                    </Border>
                </ControlTemplate>
            </Style.Resources>
            <Style.Triggers>
                <!-- 
                We can't set Template directly with DiscreteObjectKeyFrame because 
                "Cannot freeze this Storyboard timeline tree for use across threads".

                So instead we kludge it by setting Tag and putting a trigger on that. 
                -->
                <Trigger 
                    Property="Tag" 
                    Value="ButtonHasBeenPressed"
                    >
                    <Setter 
                        Property="Template" 
                        Value="{StaticResource PressedTemplate}" 
                        />
                </Trigger>
                <Trigger Property="IsPressed" Value="True">
                    <!-- 
                    Values set by a Trigger setter are automatically rolled 
                    back when the Trigger condition no longer applies. This 
                    is not true of values applied by a Storyboard in an enter 
                    action. 
                    -->
                    <Trigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <ObjectAnimationUsingKeyFrames 
                                    BeginTime="00:00:00" 
                                    Storyboard.TargetProperty="Tag"
                                    >
                                    <DiscreteObjectKeyFrame 
                                        KeyTime="00:00:00" 
                                        Value="ButtonHasBeenPressed" 
                                        />
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </Trigger.EnterActions>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Button.Style>
</Button>

Вы также можете использовать код позади.

Предположим, что кнопка:

<Button Click="Button_Click">
  <Image Source="/Image1.png"/>
</Button>

Тогда код позади может быть:

private void Button_Click(object sender, RoutedEventArgs e)
{
    var b = sender as Button;

    if (b == null)
        return;

    var image = new Image { Source = GetImageSource(), };

    b.Content = image;
}

private BitmapImage GetImageSource()
{
    var imageSource = new BitmapImage();

    imageSource.BeginInit();
    imageSource.UriSource = new Uri("/Image2.png", UriKind.Relative);
    imageSource.EndInit();

    return imageSource;
}

Это упрощенная версия, которая загружает новое изображение каждый раз, когда пользователь нажимает. Если вы хотите избежать ненужной вторичной загрузки, вы можете установить частный флаг, такой как private bool _imageSet; и установить его на Button_Click метод.

Вы также можете загрузить новое изображение заранее при инициализации Window (или UserControl).

В конце концов, я предлагаю вам поместить все изображения в ResourceDictionary и вызывать их через приложение через StaticResourceKeyи не используя все URI. Но это другая тема.

Другие вопросы по тегам