1
votes

I am making a small UWP app in which each page has a similar layout. I have created a custom UserControl following this thread, but I am not able to wrap my head around how to pass an Image Source to the background image of the UserControl.

If I remove the references to bgImage, and only mainContent, the whole thing works as expected.

How do I pass a background image source or URI to a UserControl for use with a control?

UserControl XAML:

<UserControl
    x:Class="App1.MainTemplate"
    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"
    d:DesignHeight="300"
    d:DesignWidth="400">

    <Grid Background="Black">
        <!-- Background image grid -->
        <Grid Margin="0">
            <Grid.Background>
                <ImageBrush Opacity="100" ImageSource="{x:Bind bgImage}" Stretch="UniformToFill"/>
            </Grid.Background>

            <!-- Content grid -->
            <Grid Margin="25" x:Name="contentGrid" Opacity="100">
                <!-- Darkened insert -->
                <Border BorderThickness="1" CornerRadius="8" BorderBrush="Black">
                    <Rectangle Name="Background" Opacity="0.55" Fill="Black" />
                </Border>

                <StackPanel VerticalAlignment="Center">
                    <!-- Content here. -->
                    <ContentPresenter Content="{x:Bind mainContent}" />

                </StackPanel>
            </Grid>
        </Grid>
    </Grid>
</UserControl>

MainTemplate.CS:

   public sealed partial class MainTemplate : UserControl
    {
        public MainTemplate()
        {
            this.InitializeComponent();
        }

        public static readonly DependencyProperty bgImageProperty = DependencyProperty.Register("bgImage", typeof(ImageSource), typeof(MainTemplate), new PropertyMetadata(null));
        public object bgImage
        {
            get { return GetValue(bgImageProperty); }
            set { SetValue(bgImageProperty, value); }
        }

        public static readonly DependencyProperty mainContentProperty = DependencyProperty.Register("mainContent", typeof(object), typeof(MainTemplate), new PropertyMetadata(null));
        public object mainContent
        {
            get { return GetValue(mainContentProperty); }
            set { SetValue(mainContentProperty, value); }
        }

    }

And finally, an example from one of the pages I am trying to use (MainPage.xaml):

<local:MainTemplate>
    <local:MainTemplate.bgImage>
        <Image Source="Assets/backgrounds/tailings 2.jpg"/>
    </local:MainTemplate.bgImage>

    <local:MainTemplate.mainContent>
        <Button 
                    x:Name="app1" 
                    Content="" 
                    HorizontalAlignment="Center" 
                    Click="app1_Click" 
                    Width="426" 
                    Height="134" 
                    Style="{StaticResource noMouseoverHover}"
                    >
            <Button.Background>
                <ImageBrush ImageSource="Assets/logos/image.png"/>
            </Button.Background>
        </Button>
    </local:MainTemplate.mainContent>

</local:MainTemplate>

The error I get on compile/run is:

Error       Invalid binding path 'bgImage' : Cannot bind type 'System.Object' to 'Windows.UI.Xaml.Media.ImageSource' without a converter    App1    
2
Not 100% sure how to solve it but you are using the type-safe x:Bind on an object typed property. Could be just public ImageSource bgImage { ...}.Henk Holterman

2 Answers

1
votes

As already shown in Matt's answer, the type of the bgImage property should be ImageSource:

public ImageSource bgImage
{
    get { return (ImageSource)GetValue(bgImageProperty); }
    set { SetValue(bgImageProperty, value); }
}

Besides that, you can't assign an Image control to the property, as you are trying to do here:

<local:MainTemplate>
    <local:MainTemplate.bgImage>
        <Image Source="Assets/backgrounds/tailings 2.jpg"/>
    </local:MainTemplate.bgImage>
    ...
</local:MainTheme>

Instead, you should assign a BitmapImage, like:

<local:MainTemplate>
    <local:MainTemplate.bgImage>
        <BitmapImage UriSource="Assets/backgrounds/tailings 2.jpg"/>
    </local:MainTemplate.bgImage>
    ...
</local:MainTheme>

Or shorter, taking advantage of built-in type conversion:

<local:MainTheme bgImage="/Assets/backgrounds/tailings 2.jpg">
    ...
</local:MainTheme>

In addition to the above, you should also set the x:Bind Mode to OneWay, because the default is OneTime. Later changes to the bgImage property would otherwise be ignored:

<ImageBrush ImageSource="{x:Bind bgImage, Mode=OneWay}" ... />

Finally, there are widely accepted naming conventions regarding property names in .NET. They should start with an uppercase letter, so yours should probably be BgImage.

0
votes

Don't you just need to set the property to be an ImageSource and not an object

public ImageSource bgImage
{
    get { return (ImageSource)GetValue(bgImageProperty); }
    set { SetValue(bgImageProperty, value); }
}