2

我想通过添加第二个来源来扩展 Image 类。我想在 XAML 中定义第二个源(如原始源)并在鼠标进入/离开此图像时更改这些图像。

我试过自己:

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;
        }
    }

但它不起作用,我认为我做错了。有人可以帮忙吗?

[更新]

我写了这个:

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;
    }
}

但有时它可以工作,有时会出现异常:“PresentationCore.dll 中发生了类型为 'System.ArgumentException' 的未处理异常

附加信息:该值超出预期范围。”


我不确定我是否理解,但我试过这个:

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;
    }
}

仍然一无所有。我在做什么错?

4

4 回答 4

4

请参阅MSDN 上的自定义依赖属性文章。事件连接属于您的依赖属性的PropertyChangedCallback.

我还建议使用触发器而不是事件处理。但是,这并不意味着您需要在要使用它的任何地方复制 XAML。您可以使用默认样式的图像切换触发器定义自定义控件(请参阅控件创作概述中的“在主题级别定义资源” )。哪里MouseOverImageControl带有“Source”和“Source2”依赖属性的,你可以定义这个默认样式:

<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>

如果您使用事件处理程序,则需要存储 Source 的原始值,添加一个MouseLeave将其还原的处理程序,并考虑用户重新分配SourceSource2随时重新分配的情况。使用带有两个单独的“Source”和“Source2”绑定的触发器解决方案,所有这些都是自动处理的。

编辑

但有时它可以工作,有时会出现异常:“PresentationCore.dll 中发生了类型为 'System.ArgumentException' 的未处理异常

附加信息:该值超出预期范围。”

我的猜测是在源更改之后但在将其应用于布局之前触发,因此和HitTestCore之间存在差异。我不确定将这些包含在计算中的理由(它们不应该总是相同的吗?)尝试使用以下内容:ActualWidthsource.PixelWidth

var x = (int)hitTestParameters.HitPoint.X;
var y = (int)hitTestParameters.HitPoint.Y; 
于 2013-08-19T15:15:22.440 回答
4

扩展图像是一种矫枉过正,您所要做的就是定义一种样式,该样式将使用触发器来交换源

<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>
于 2013-08-19T14:36:43.377 回答
1

您不需要扩展Image类来执行此操作。Image类上有一个属性IsMouseOver,您可以触发它来切换Source图像。把它放在你的视图中,你就万事俱备了。

于 2013-08-19T13:57:48.730 回答
0

您需要将新属性添加为Dependency Property. 您可以从MSDN的DependencyProperties 概述页面中找到更多信息,但基本思想是这样的:

您首先创建Dependency Property

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

然后,您可以选择使用标准 CLR 属性添加包装器(仅供您自己使用):

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

(代码示例取自链接文章)

于 2013-08-19T13:57:58.810 回答