我想通过添加第二个源来扩展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;
}
}
但它不起作用,我认为我做错了。有人可以帮忙吗?
[UPDATE]
我写了这个:
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;
}
}
仍然没有。我做错了吗?
答案 0 :(得分: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>
答案 1 :(得分:3)
请参阅Custom Dependency Properties article on MSDN。事件连接属于您的依赖项属性PropertyChangedCallback
。
我还建议使用触发器而不是事件处理。但是,这并不意味着您需要在任何想要使用它的地方复制XAML。您可以使用默认样式的图像切换触发器定义自定义控件(请参阅Control Authoring Overview中的“在主题级别定义资源”)。其中MouseOverImage
是具有“Source”和“Source2”依赖项属性的Control
,您可以定义此默认样式:
<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
处理程序,并考虑用户重新分配Source
或{{1在任何时候。使用具有两个单独的“Source”和“Source2”绑定的触发器解决方案,所有这些都将自动处理。
修改强>
但有时它有效,有时会有例外:“未经处理 发生在'System.ArgumentException'类型的异常 PresentationCore.dll中
附加信息:该值超出预期范围。“
我的猜测是Source2
在源更改后但在应用于布局之前触发,因此HitTestCore
和ActualWidth
之间存在差异。我不确定在计算中包含这些的理由(它们不应该总是相同吗?)尝试使用以下内容:
source.PixelWidth
答案 2 :(得分:1)
您无需扩展Image
类来执行此操作。名为Image
的{{1}}课程中有一个属性,您可以触发该属性来切换图片的IsMouseOver
。将它放在视图中的样式中,您就可以完成所有设置。
答案 3 :(得分:0)
您需要将新属性添加为Dependency Property
。您可以在MSDN的DependencyProperties Overview页面上找到更多信息,但基本的想法是:
首先创建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); }
}
(代码示例取自链接文章)