0

I have a control that a user builds in the settings menu. I am going to give them the option of either uploading an image as the background of the control, or setting the background colors. How would I allow the user to toggle this functionality without having to create a whole new control, or without having to create two parent grids with toggled visibility (which would double the page xaml)?

Here is the xaml. When I manually comment one of the Grid.Background tags out, I can toggle between colors and images. How do I do this programatically?

<Grid Name="myGrid">        
      <Grid.Background>
           <ImageBrush ImageSource="c:/sports.jpeg" Stretch="UniformToFill"/>
      </Grid.Background>

      <Grid.Background>
           <LinearGradientBrush StartPoint="0,1" EndPoint="0,.5">
                 <LinearGradientBrush.GradientStops>
                      <GradientStop Color="{Binding ColorsBo.PageBackgroundPrimary}" Offset="1"/>
                        <GradientStop Color="{Binding ColorsBo.PageBackgroundGradient}" Offset="0"/>
                    </LinearGradientBrush.GradientStops>
           </LinearGradientBrush>
      </Grid.Background> 

       .... more xaml to fill the page
</Grid>
nikotromus
  • 1,015
  • 16
  • 36
  • `myGrid.Background = new ImageBrush(...)` or `myGrid.Background = new LinearGradientBrush(...)` – Clemens Oct 26 '18 at 18:57
  • I disagree. If someone is struggling like I was on how to toggle a gradient brush with a image brush, they're going to Michael's fantastic answer because you marked it as a duplicate. – nikotromus Oct 26 '18 at 20:03
  • You can simply assign instances of any Brush-derived class to an element's Background property. That's trivial and does not *require* a view model. While binding the Background property is fine, it isn't strictly necessary. When you ask how to programatically toggle the Background between an ImageBrush and a LinearGradientBrush, a straightforward answer is to set the property to an instance of each. – Clemens Oct 26 '18 at 20:06
  • Duplicates are linked and can be seen in the sidebar. People struggling will often visit the duplicate links to read the other answers. Nothing is lost by marking a post as a duplicate. –  Oct 26 '18 at 22:53

1 Answers1

1

You basically answered the question yourself in your code.

The Grid.Background is a DependencyProperty of Type Brush. This means we can bind any Brush to the Grid.

How you choose to do this binding is up to you and a lot of cool styles / features can be gained from it.

Here's a very basic ViewModel that sort of demonstrates this.

using System.ComponentModel;
using System.Windows.Media;

namespace Question_Answer_WPF_App
{
    public class BackgroundViewModel : INotifyPropertyChanged
    {
        private readonly SolidColorBrush DefaultBrush = new SolidColorBrush(Colors.BlueViolet);
        private Brush background;
        public event PropertyChangedEventHandler PropertyChanged;
        public BackgroundViewModel() => background = DefaultBrush;

        public Brush Background
        {
            get => background;
            set
            {
                background = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Background)));
            }
        }
    }
}

Then you might use it like so...

<Grid Name="myGrid"
      Background="{Binding Background}"> 
...

Just to help you out I've done you one a little better. Here's some preset brushes in a ViewModel, and a Grid in a View. You can copy and paste the guts of this as is, no code behind, and it will work. (Notice I've used 3 different Brushes on purpose; SolidColorBrush, ImageBrush, and LinearGradientBrush. There are more and any can be used.)

ViewModel

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace Question_Answer_WPF_App.ViewModels
{
    public class BackgroundViewModel : INotifyPropertyChanged
    {
        private Brush selectedBackground;

        public BackgroundViewModel()
        {
            var brushes = new List<Brush>
            {
                new SolidColorBrush(Colors.BlueViolet),
                new ImageBrush(new BitmapImage(new Uri("https://i.stack.imgur.com/jGlzr.png", UriKind.Absolute))),
                new LinearGradientBrush(Colors.Black, Colors.White, 45)
            };
            BackgroundOptions = brushes;
            SelectedBackground = BackgroundOptions.FirstOrDefault();
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public IEnumerable<Brush> BackgroundOptions { get; }

        public Brush SelectedBackground
        {
            get => selectedBackground;
            set
            {
                selectedBackground = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedBackground)));
            }
        }
    }
}

View

<Window x:Class="Question_Answer_WPF_App.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:ViewModels="clr-namespace:Question_Answer_WPF_App.ViewModels"
        mc:Ignorable="d"
        Title="MainWindow"
        Height="500"
        Width="800">

    <Window.DataContext>
        <ViewModels:BackgroundViewModel />
    </Window.DataContext>

    <Grid Background="{Binding SelectedBackground}">
        <ComboBox ItemsSource="{Binding BackgroundOptions}"
                  SelectedItem="{Binding SelectedBackground}"
                  Width="250"
                  Height="40"
                  VerticalAlignment="Top"
                  HorizontalAlignment="Left"
                  Margin="12">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <Grid Background="{Binding}"
                          Height="40"
                          Width="200" />
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
    </Grid>

</Window>

Screen Shots

enter image description here

enter image description here

enter image description here

Michael Puckett II
  • 6,586
  • 5
  • 26
  • 46