0

I wanna make a custom usercontrol which actually just a image button.
Here is my project:
enter image description here


Here is code of ImageButton.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Controls;

namespace App1.UC
{
    class ImageButton:Button
    {


        public ImageSource BackgroundImage
        {
            get { return (ImageSource)GetValue(BackgroundImageProperty); }
            set { SetValue(BackgroundImageProperty, value); }
        }

        // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty BackgroundImageProperty =
            DependencyProperty.Register("BackgroundImage", typeof(ImageSource), typeof(ImageButton), null);


    }
}

Here is code of ImageButton.xaml:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App1.UC">
    <Style TargetType="local:ImageButton">
        <Style.Setters>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <Grid>
                            <Border Background="{Binding local:BackgroundImage}"></Border>
                            <Border Background="Blue"></Border>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style.Setters>
    </Style>
</ResourceDictionary>

And here is code of MainPage.xaml:

<Page xmlns:my="using:App1.UC" 
    x:Class="App1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App1"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    <Page.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/UC/ImageButton.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Page.Resources>
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <my:ImageButton Height="100" Width="100" BackgroundImage="Assets/Wide310x150Logo.png" />
    </Grid>
</Page>


The problem is I can't see the BackgroundImage which I set in my:ImageButton.
I doubted if is something wrong with binding the BackgroundImage in ImageButton.xaml.
I googled about it and found something like How to bind to attached property in UWP?
I tried as it said:

{Binding Path=(local:ImageButton.BackgroundImage), RelativeSource={RelativeSource Self}}

But no use again.
What's wrong with my programme?Would you please help me ?

Justin XL
  • 38,763
  • 7
  • 88
  • 133
Melon NG
  • 2,568
  • 6
  • 27
  • 52
  • `class ImageButton : Button` declares a derived Button class, not a UserControl. That class won't magically load a ResourceDictionary in a file that accidentially has the same name as the class. Either create a proper UserControl in your Visual Studio project, or take a look at [custom controls with default Styes](https://learn.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.control#Windows_UI_Xaml_Controls_Control_DefaultStyleKey). – Clemens Aug 19 '17 at 17:23
  • Why are you trying to create your own derived version of a button? as rightly said by @Clemens it just won't work this ways. Why don't you edit the style of the Button Control is all you want to do is change the way the button looks. – iam.Carrot Aug 19 '17 at 19:31
  • @Clemens Beaucase I wanna to inherit the property of Button,such as foreground fontsize and etc.Is there a better way to inherit Button? – Melon NG Aug 20 '17 at 00:25
  • @AdityaSharma I am not only want to change the style but also want to add a custom property names BackgroundImage.But what is the best way to do ti? – Melon NG Aug 20 '17 at 00:26
  • What does the your backgroundImage property do? – iam.Carrot Aug 20 '17 at 05:55
  • "Is there a better way to inherit Button?" There is only *one* way to inherit from Button. That's how you did it. However, if you want to declare a default Style for the derived Button, it has to be in a ResourceDictionary called `Generic.xaml` in a `Themes` folder in your Visual Studio project. You also need to set the derived Button's `DefaultStyleKey` property. Read the online documentation. – Clemens Aug 20 '17 at 06:36
  • @AdityaSharma Well,the button has a background color and a background image,I want to use background property to binding the background color,and the custom property BackgroundImage to binding the background image. – Melon NG Aug 20 '17 at 07:55
  • So you want the background image and a background colour at the same time? Am I getting it right? – iam.Carrot Aug 20 '17 at 08:22
  • @AdityaSharma yeah,that's why I used border twice in the xaml,one border to show the background image and one border to show the background color. – Melon NG Aug 20 '17 at 08:30
  • Do you want to have a button with background colour and a background picture is that what you want? Both dynamically set at runtime – iam.Carrot Aug 20 '17 at 08:32
  • @AdityaSharma yes,that's what I need as you said.I just found a tutorial maybe helpful:http://www.wyzard.us/creating-a-custom-native-control-in-uwp-3/ .However I followed the tutorial,but the programme crash at the binding in BackgroundImage again. – Melon NG Aug 20 '17 at 08:36
  • @AdityaSharma I tried Justin XL's answer,it works now~ – Melon NG Aug 20 '17 at 08:48

1 Answers1

2

You don't have to extend the Button just for displaying an image as its background. You can use ImageBrush directly like this

<Button>
    <Button.Background>
        <ImageBrush ImageSource="Assets/Wide310x150Logo.png" />
    </Button.Background>
</Button>

Update

Extending an existing control with additional dependency properties can be simplified to the following steps.

1. Right click on your project, then go Add > New Item.... In the popup, select Templated Control and give it a name ImageButton.cs.

[![enter image description here][1]][1]

Visual Studio will now automatically generate a new folder called
`Themes` with a `ResourceDictionary` file named `Generic.xaml`,
which is where the default style of your `ImageButton` goes.

[![enter image description here][2]][2]

Visual Studio will also generate an `ImageButton` class with the
following code.

    public sealed class ImageButton : Control
    {
        public ImageButton()
        {
            this.DefaultStyleKey = typeof(ImageButton);
        }
    }

2. Change the base class to Button and add your own dependency property to the class.

    public sealed class ImageButton : Button

    public ImageSource BackgroundImage
    {
        get { return (ImageSource)GetValue(BackgroundImageProperty); }
        set { SetValue(BackgroundImageProperty, value); }
    }

    // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty BackgroundImageProperty =
        DependencyProperty.Register("BackgroundImage", typeof(ImageSource), typeof(ImageButton), null);

3. Provide your own style and put it inside Generic.xaml. Note you will need to use TemplateBinding to pass values from your dependency properties to the binding targets.

        <Style TargetType="local:ImageButton">
            <Style.Setters>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="local:ImageButton">
                            <Grid>
                                <Image Stretch="UniformToFill" Source="{TemplateBinding BackgroundImage}"></Border>
                                ...
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style.Setters>
        </Style>

That's it. Now, you can use it like below

<my:ImageButton Height="100" Width="100" BackgroundImage="Assets/Wide310x150Logo.png" />
Justin XL
  • 38,763
  • 7
  • 88
  • 133
  • It is the easiest way which I used to do it.However,there is so many place need to use the ImageButton.It is so troublesome that always type the code or copy/paste the code.So I want to make a usercontrol to make it more convenient to use. – Melon NG Aug 20 '17 at 07:53
  • UserControl? But from the code in your question, you are creating a custom control. What exactly are you trying to do here? – Justin XL Aug 20 '17 at 08:26
  • I am sorry about my mistake.It is custom control but not usercontrol. – Melon NG Aug 20 '17 at 08:31
  • Yes,it works.But I found another problem and solved it.The problem is I used Border to show the background image,but the it won't show the image.I should use Image to show it instead. – Melon NG Aug 20 '17 at 08:47
  • Thank you very much for help! – Melon NG Aug 20 '17 at 08:47
  • Yeah you will need to use `ImageBrush` if you want to use a `Border`. But I'd go with `Image` as it does automatic decoding. – Justin XL Aug 20 '17 at 08:49