alduin
alduin

Reputation: 317

How do I change window background image dynamically in WPF with a button click?

I want to change or "scroll through" different background images for the main window based on a button click. The number of different backgrounds will be dynamic and will be based on something like the number of images in a specific folder. So each time the program loads there could be a different number of backgrounds to scroll through.

I also want to be able to go back to the previous background image, so the whole thing kind of acts like a carousel. Example: the program loads and A.jpg is loaded as background image. I click the "Right" button and A.jpg slides off to the left, and then B.jpg slides in from the right to become the new background image. I click "Right" again and C.jpg slides in from the right. I then click "Left" and B.jpg slides back in from the left side, etc. etc.

Hopefully that makes sense. I'm quite new to XAML and WPF so just trying to figure out how I would go about doing this. Any help or guidance would be much appreciated. Thanks!

Upvotes: 0

Views: 2532

Answers (2)

c0d3b34n
c0d3b34n

Reputation: 563

I would use a ListView and an ObservableCollection<string> in ViewModel. The ObservableCollection<string> contains a dynamic list of paths to the images. Be sure that the Build Action of the images is set to Resource. Then within the Background Property of Window place an ImageBrush where you bind the Source Property to the SelectedItem Property of ListView. The path strings of images follows a scheme you can find here: https://learn.microsoft.com/en-us/dotnet/framework/wpf/app-development/pack-uris-in-wpf

As desired (Images are BuildAction to Resource and copy if newer):

MainWindow.xaml

<Window x:Class="WinTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WinTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <local:TestViewModel x:Key="viewModel"/>
        <local:ImageConverter x:Key="converter"/>
    </Window.Resources>
    <Window.DataContext>
        <Binding Source="{StaticResource viewModel}" IsAsync="True"/>
    </Window.DataContext>
    <Window.Background>
        <ImageBrush ImageSource="{Binding SelectedImagePath, Converter={StaticResource converter}}"/>
    </Window.Background>
    <Grid Background="Transparent">
        <ListView Background="Transparent" SelectedValue="{Binding SelectedImagePath, Mode=TwoWay}" ItemsSource="{Binding PathList}"/>
    </Grid>
</Window>

TestViewModel.cs (Collection can used as string or Uri list. You have to instanciate a new Uri in Converter from value if you use strings)

public class TestViewModel : BasePropertyChangeNotification
{
    public ObservableCollection<Uri> PathList
    {
        get;
        private set;
    }

    public Uri SelectedImagePath
    {
        get { return this.selectedImagePath; }
        set { this.SetProperty(ref this.selectedImagePath, value); }
    }
    private Uri selectedImagePath = new Uri("pack://application:,,,/Images/img1.jpg", UriKind.RelativeOrAbsolute);

    public TestViewModel()
    {
        this.PathList = new ObservableCollection<Uri>
        {
            new Uri("pack://application:,,,/Images/img1.jpg", UriKind.RelativeOrAbsolute),
            new Uri("pack://application:,,,/Images/img2.jpg", UriKind.RelativeOrAbsolute),
            new Uri("pack://application:,,,/Images/img3.jpg", UriKind.RelativeOrAbsolute),
            new Uri("pack://application:,,,/Images/img4.jpg", UriKind.RelativeOrAbsolute),
            new Uri("pack://application:,,,/Images/img13.jpg", UriKind.RelativeOrAbsolute)
        };
    }
}

ImageConverter.cs

public class ImageConverter : IValueConverter
{
    public object Convert(
        object value, Type targetType, object parameter, CultureInfo culture)
    {
        return new BitmapImage(value as Uri);
    }

    public object ConvertBack(
        object value, Type targetType, object parameter, CultureInfo culture)
    {
        return Binding.DoNothing;
    }
}

That's all.

Upvotes: 2

Hammas_Stack1
Hammas_Stack1

Reputation: 182

That's how you can do this ! I have tested it . You can apply animations for carousel type effects.

public MainWindow()
{
    InitializeComponent();

    myImagesList = new List<ImageBrush>();
    ImageBrush myBrush1 = new ImageBrush(new BitmapImage(new Uri(@"C:\Users\Abdul Rehman\Desktop\1-Rao Hammas Folder\MY PROJECTS\StackOverFlowSolutions\StackOverFlowSolutions\Images\Capture.JPG")));
    ImageBrush myBrush2 = new ImageBrush(new BitmapImage(new Uri(@"C:\Users\Abdul Rehman\\Desktop\1-Rao Hammas Folder\MY PROJECTS\StackOverFlowSolutions\\StackOverFlowSolutions\Images\\Apps-Dialog-Close-icon.png")));
    ImageBrush myBrush3 = new ImageBrush(new BitmapImage(new Uri(@"C:\Users\Abdul Rehman\\Desktop\1-Rao Hammas Folder\MY PROJECTS\StackOverFlowSolutions\\StackOverFlowSolutions\Images\\Capture.JPG")));
    ImageBrush myBrush4 = new ImageBrush(new BitmapImage(new Uri(@"C:\Users\Abdul Rehman\\Desktop\1-Rao Hammas Folder\MY PROJECTS\StackOverFlowSolutions\\StackOverFlowSolutions\Images\\Capture.JPG")));
    ImageBrush myBrush5 = new ImageBrush(new BitmapImage(new Uri(@"C:\Users\Abdul Rehman\\Desktop\1-Rao Hammas Folder\MY PROJECTS\StackOverFlowSolutions\\StackOverFlowSolutions\Images\\Capture.JPG")));    

    myImagesList.Add(myBrush1);
    myImagesList.Add(myBrush2);
    myImagesList.Add(myBrush3);
    myImagesList.Add(myBrush4);
    myImagesList.Add(myBrush5);


    MainWin.Background = myImagesList[index];
}
private int index = 0;
private List<ImageBrush> myImagesList;

private void NextBtn_Click(object sender, RoutedEventArgs e)
{
    index++;
    MainWin.Background = myImagesList[index];
}

private void PrevBtn_Click(object sender, RoutedEventArgs e)
{
    index--;
    MainWin.Background = myImagesList[index];
}  

XAML

<Window x:Class="StackOverFlowSolutions.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Name="MainWin"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Button Name="NextBtn" Width="30" Height="20" Click="NextBtn_Click">Next</Button>
        <Button Name="PrevBtn" Width="30" Height="20" Margin="297,111,176,180" Click="PrevBtn_Click">Prev</Button>
    </Grid>
</Window>

Upvotes: 0

Related Questions