2 votes

Image WPF avec deux sources

J'aimerais étendre la classe Image en ajoutant une deuxième source. Je veux définir la deuxième source dans XAML (comme la source originale) et changer ces images lorsque la souris entre/quitte cette image.

J'ai essayé avec :

class MainMenuImageButton : Image
    {
        public static readonly DependencyProperty Source2Property;
        public ImageSource Source2 
        {
            get { return Source2; }
            set
            {
                this.MouseEnter+=new System.Windows.Input.MouseEventHandler(MainMenuImageButton_MouseEnter);
            }
        }
        public void MainMenuImageButton_MouseEnter(object sender, MouseEventArgs e)
        {
            this.Source = Source2;
        }
    }

Mais cela ne fonctionne pas et je pense que je m'y prends totalement mal. Quelqu'un peut-il m'aider ?

[MISE À JOUR]

J'ai écrit ceci :

class MainMenuImageButton : Image
{
    protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
    {
        var source = (BitmapSource)Source;
        var x = (int)(hitTestParameters.HitPoint.X / ActualWidth * source.PixelWidth);
        var y = (int)(hitTestParameters.HitPoint.Y / ActualHeight * source.PixelHeight);
        var pixels = new byte[4];
        source.CopyPixels(new Int32Rect(x, y, 1, 1), pixels, 4, 0);
        if (pixels[3] < 10) return null;
        return new PointHitTestResult(this, hitTestParameters.HitPoint);
    }
    public ImageSource Source1
    {
        get { return GetValue(ImageSourceProperty) as ImageSource; }
        set { base.SetValue(ImageSourceProperty, value); }
    }
    public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register("Source1", typeof(ImageSource), typeof(MainMenuImageButton));
    public ImageSource Source2
    {
        get { return GetValue(ImageSource2Property) as ImageSource; }
        set { base.SetValue(ImageSource2Property, value); }
    }
    public static readonly DependencyProperty ImageSource2Property = DependencyProperty.Register("Source2", typeof(ImageSource), typeof(MainMenuImageButton));
    public MainMenuImageButton() : base() 
    {
        this.MouseEnter += new MouseEventHandler(MainMenuImageButton_MouseEnter);
        this.MouseLeave += new MouseEventHandler(MainMenuImageButton_MouseLeave);
    }

    void MainMenuImageButton_MouseLeave(object sender, MouseEventArgs e)
    {
        this.Source = this.Source1;
    }

    void MainMenuImageButton_MouseEnter(object sender, MouseEventArgs e)
    {
        this.Source = this.Source2;
    }
}

Mais parfois cela fonctionne et parfois il y a des exceptions : "Une exception non gérée de type 'System.ArgumentException' s'est produite dans PresentationCore.dll.

Informations complémentaires : La valeur est en dehors de la fourchette prévue".


Je ne suis pas sûr d'avoir compris, mais j'ai essayé :

class MainMenuImageButton : Image
{
    public static readonly DependencyProperty Source2Property = DependencyProperty.Register("Source2", typeof(ImageSource), typeof(MainMenuImageButton), new PropertyMetadata(true));
    public ImageSource Source2 
    {
        get { return (ImageSource)GetValue(Source2Property); }
        set
        {
            BitmapImage logo = new BitmapImage(new Uri(value.ToString(), UriKind.Relative));
            SetValue(Source2Property, logo); 
            this.MouseEnter+=new System.Windows.Input.MouseEventHandler(MainMenuImageButton_MouseEnter);
        }
    }
    public void MainMenuImageButton_MouseEnter(object sender, MouseEventArgs e)
    {
        this.Source = Source2;
    }
}

Et toujours rien. Qu'est-ce que je fais de travers ?

4voto

makc Points 1475

Il suffit de définir un style qui utilisera le déclencheur pour intervertir les sources.

<Image>
  <Image.Style>
    <Style TargetType="{x:Type Image}">
      <Setter Property="Source" Value="Image1"/>
      <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
          <Setter Property="Source" Value="Image2"/>
        </Trigger>
      </Style.Triggers>
    </Style>
  </Image.Style>
</Image>

4voto

nmclean Points 4251

Se référer à la Article sur les propriétés de dépendance personnalisées sur MSDN . L'accroche de l'événement se trouve dans la section PropertyChangedCallback .

Je suggère également d'utiliser un déclencheur au lieu d'une gestion d'événements. Cependant, cela ne signifie pas que vous devrez dupliquer le XAML partout où vous souhaitez l'utiliser. Vous pouvez définir un contrôle personnalisé avec le déclencheur de changement d'image dans son style par défaut (voir "Définir les ressources au niveau du thème" dans la section Vue d'ensemble de la création de contrôles ). Où l'on trouve MouseOverImage es un Control avec les propriétés de dépendance "Source" et "Source2", vous pouvez définir ce style par défaut :

<Style TargetType="local:MouseOverImage">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:MouseOverImage">
                <Grid>
                    <Image Name="SourceImage" Source="{TemplateBinding Source}" />
                    <Image Name="Source2Image" Source="{TemplateBinding Source2}" Visibility="Hidden" />
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter TargetName="SourceImage" Property="Visibility" Value="Hidden" />
                        <Setter TargetName="Source2Image" Property="Visibility" Value="Visible" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Si vous utilisez des gestionnaires d'événements, vous devrez stocker la valeur originale de Source, ajouter une fonction MouseLeave qui l'annule, et envisager également le cas où un utilisateur réaffecte des Source o Source2 à tout moment. En utilisant la solution du déclencheur avec deux liens distincts "Source" et "Source2", tout cela est géré automatiquement.

EDIT

Mais parfois cela fonctionne et parfois il y a des exceptions : "Une exception non gérée exception de type 'System.ArgumentException' s'est produite dans le fichier PresentationCore.dll

Informations complémentaires : La valeur est en dehors de la fourchette prévue".

Je pense que HitTestCore est déclenché après que la source ait été modifiée mais avant qu'elle ne soit appliquée à la mise en page, de sorte qu'il y a un décalage entre ActualWidth y source.PixelWidth . Je ne suis pas certain de la raison pour laquelle ces éléments sont inclus dans le calcul (ne devraient-ils pas toujours être les mêmes ?) Essayez d'utiliser ce qui suit :

var x = (int)hitTestParameters.HitPoint.X;
var y = (int)hitTestParameters.HitPoint.Y;

1voto

Thelonias Points 2126

Il n'est pas nécessaire d'étendre le Image pour ce faire. Il existe une propriété sur la classe Image classe appelée IsMouseOver que vous pouvez déclencher pour faire basculer le Source de votre image. Placez ceci dans un style de votre vue et vous serez prêt.

0voto

Sheridan Points 26778

Vous devez ajouter la nouvelle propriété en tant que Dependency Property . Pour en savoir plus, consultez le site Aperçu des propriétés de dépendance à MSDN, mais l'idée de base est la suivante :

Vous créez d'abord le Dependency Property :

public static readonly DependencyProperty IsSpinningProperty = DependencyProperty.Register(
"IsSpinning", typeof(Boolean), typeof(YourClassName), new PropertyMetadata(true));

Ensuite, vous peut ajouter éventuellement une enveloppe utilisant les propriétés CLR standard (pour votre propre usage uniquement) :

public bool IsSpinning
{
    get { return (bool)GetValue(IsSpinningProperty); }
    set { SetValue(IsSpinningProperty, value); }
}

(L'exemple de code est tiré de l'article en lien)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X