简体   繁体   中英

WPF Custom Control - Button Event

I start the WPF today, I'm trying to implement a custom control.

My problem is that I can not select an element in the template.

My code:

[Generic.xaml]

 <Style x:Key="{x:Type local:ImageButton}" TargetType="{x:Type local:ImageButton}"  BasedOn="{StaticResource {x:Type Button}}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:ImageButton}">
                <StackPanel>
                    // -> My image
                    <Image Source="{Binding Path=Tag, RelativeSource={RelativeSource TemplatedParent}}"></Image>
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

[ImageButton.cs]

public class ImageButton : Button
{
    public Image imageOff { get; set; }
    public Image imageOn { get; set; }

    static ImageButton()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(ImageButton), new FrameworkPropertyMetadata(typeof(ImageButton)));
    }

    public ImageButton()
        : base()
    {
        this.MouseEnter += new MouseEventHandler(SetImageON);
    }

    public void SetImageON(object sender, MouseEventArgs e)
    {
       //Here i wanna change my image from StackPanel
    }
}

Am I on the good way ? How can I change that image?

sender is your control so you could also right this.SetCurrentValue.

public void SetImageON(object sender, MouseEventArgs e)
{
    ImageButton btn = (ImageButton)sender;
    btn.SetCurrentValue(TagProperty,imageOn.Source);
}

it seems as though you might wan't to just save the source of your image in the control , instead of the entire image.

But if you wan't to use an Image object in code like this

xaml : in your template .

  <StackPanel x:Name="myPanel" />

cs : in your control :

 myPanel.Children.Add(imageOn);

Give a name to your image, like x:Name="PART_Image" . Then in your code behind override OnApplyTemplate method and store it into a variable.

private Image PART_Image;

public override void OnApplyTemplate()
{
  PART_Image = this.GetTemplatedChild("PART_Image");
}

In this case you can access it in your method like:

this.PART_Image.Visibility = Visibility.Collapsed;

You can achieve what you want with a Trigger:

<Style x:Key="{x:Type local:ImageButton}" TargetType="{x:Type local:ImageButton}" BasedOn="{StaticResource {x:Type Button}}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:ImageButton}">
                <StackPanel>
                    <Image Source="{Binding Path=imageOff.Source, RelativeSource={RelativeSource TemplatedParent}}">
                        <Image.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Image.Source" Value="{Binding Path=imageOn.Source, RelativeSource={RelativeSource TemplatedParent}}" />
                            </Trigger>
                        </Image.Triggers>
                    </Image>
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

That way you don't need the event in the code-behind. If you wanted to, you could make imageOff and imageOn DependencyProperties, that way you could define the source images in xaml too:

public class ImageButton : Button {
    public static readonly DependencyProperty imageOffProperty = DependencyProperty.Register("imageOff", typeof(Image), typeof(ImageButton), new PropertyMetadata(null));
    public Image imageOff {
        get { return (Image)GetValue(imageOffProperty); }
        set { SetValue(imageOffProperty, value); }
    }

    public static readonly DependencyProperty imageOnProperty = DependencyProperty.Register("imageOn", typeof(Image), typeof(ImageButton), new PropertyMetadata(null));
    public Image imageOn {
        get { return (Image)GetValue(imageOnProperty); }
        set { SetValue(imageOnProperty, value); }
    }

    static ImageButton()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(ImageButton), new FrameworkPropertyMetadata(typeof(ImageButton)));
    }
}

So when you declare an ImageButton in xaml, you can do something like this:

<local:ImageButton imageOn="/Resource/Path/To/imageOn.png" imageOff="/Resource/Path/To/imageOff.png" />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM