Help with Data Binding and Images

DoJa

Active member
Joined
Mar 23, 2014
Messages
33
Programming Experience
1-3
I have spent the day reading up on this and finally got a working example of some code which binds an image path to a binding source.

The problem is, I can only set it once when it first loads. After that I am unable to change the image to something different. I guess it is something to do with my implementation of inotifypropertychanged, but everything compiles and runs ok without errors.

Please could someone take a look at my code and suggest where I am going wrong?

C#:
<Window x:Class="Introduction_to_WPF_Data_Binding.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:Introduction_to_WPF_Data_Binding"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Image x:Name="image" Source="{Binding MyImagePath}" HorizontalAlignment="Left" Height="160" Margin="145,33,0,0" VerticalAlignment="Top" Width="224"/>
        <Button x:Name="btnImage1" Content="Image 1" HorizontalAlignment="Left" Height="34" Margin="31,246,0,0" VerticalAlignment="Top" Width="75" Click="btnImage1_Click" />
        <Button x:Name="btnImage2" Content="Image 2" HorizontalAlignment="Left" Height="34" Margin="145,246,0,0" VerticalAlignment="Top" Width="75"/>
        <Button x:Name="btnImage3" Content="Image 3" HorizontalAlignment="Left" Height="34" Margin="256,246,0,0" VerticalAlignment="Top" Width="75"/>
        <Button x:Name="btnImage4" Content="Image 4" HorizontalAlignment="Left" Height="34" Margin="367,246,0,0" VerticalAlignment="Top" Width="75" />

    </Grid>
</Window>

C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace Introduction_to_WPF_Data_Binding
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window 
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this; //Set Data Context

           path = "img1.jpg"; //Set Default Image

        }


           string path = ""; //Create empty string for image path


            public event PropertyChangedEventHandler PropertyChanged; //Event Handler for OnProperty Changed


            private void OnPropertyChanged(string property)
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(property));
            }


            public string MyImagePath
            {
                get { return path; }
                set
                {
                    path = value;
                    OnPropertyChanged("MyImagePath");
                }
            }

        private void btnImage1_Click(object sender, RoutedEventArgs e)
        {
            path = "img4.jpg";
        }
    }

    }
 
Thank you John, I've got it working following your advice.

What does the property/identifier after the colon following the class deceleration mean and what other variations are there?

For example.

By default a new window has:

C#:
public partial class MainWindow : Window

and one of the things I had to change to make it work was to change this to

C#:
public partial class MainWindow : INotifyPropertyChanged

So what other things could I add there (if any) aside from 'window' or 'INotifyPropertyChanged' to access other features or functions?

What does ':Window' mean/do .. has removing it and replacing with 'INotifyPropertyChanged' now prevented me from accessing some features which were enabled by the ':window' ?

Also what is a Partial Class in this context compared to a 'Full' Class and why would I want one over another?


Will I need to repeat all this code for every control on the window with which I wish to use binding ? Would you advise doing it manually like this or using something like Prism?
 
That's where you specify class inheritance and interface type list. MainWindow user code is a partial class generated by designer, designer code already defines it as inheriting Window class so that is not needed. If you needed to both inherit a base class and implement one or more interfaces you would set base class first and use commas to list the interfaces. (C# language specification 10.1.4)
 
Thanks. So iNotifyPropertyChanged is an interface? and I can implement them by adding them at the top of a class , separating with commas if I need more than one?

Are these interfaces a type of method or class in themselves or a totally separate entity in their own right? Are interfaces such as iNotifyPropertyChanged a built in part of c# or WPF or are they specific to visual studio?

Is there some sort of documentation or list of all the interfaces which are available to use?
 
Yes. Yes. Interfaces are like contracts, you implement them when you have a specific contract you need to comply to. Interfaces is an abstraction that makes it easier for different objects to communicate without knowing about each others specifics.
INotifyPropertyChanged is defined in .Net Framework library. MSDN Library is where to look for documentation, using Help system in Visual Studio directs you there.
 
Thanks John.

What is the purpose of the wpf way of doing things with databinding and interfaces rather than traditional methods ... Is it really a step in the right direction? To the uninformed it seems like a massive overhead of additional lines of code which perform no direct business benefit.

Essentially all this :

C#:
public partial class MainWindow : INotifyPropertyChanged
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this; //Set Data Context

           path = "img4.jpg"; //Set Default Image

        }


           private string path = ""; //Create empty string for image path


        public event PropertyChangedEventHandler PropertyChanged; //Event Handler for OnProperty Changed


        // Create the OnPropertyChanged method to raise the event
        protected void OnPropertyChanged(string path)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(path));
            }
        }


        public string MyImagePath
            {
                get { return path; }
                set
                {
                    path = value;           

                // Call OnPropertyChanged whenever the property is updated
                OnPropertyChanged("MyImagePath");

                }
            }

to get the same output as this:

C#:
imgtest.Source = new BitmapImage(new Uri("img4.jpg", UriKind.Relative));
i
Are the benefits of the former great enough to make it a clear choice for the majority of projects (and if so what?) Or does a project need to meet a really specific criteria in order to make all the extra effort worthwhile?
 
INotifyPropertyChanged has nothing to do with WPF specifically, it is from way back .Net 2.0 and is a standard way of providing property change notification. There is no massive amount of code involved, only one event and one OnPropertyChanged method, which is just a copy-paste. It would work equally well with just the event and raising that, but using a protected On...Changed method is a standard way of implementing events in .Net code according to design guidelines.

WPF has also its own system with DependencyProperty and built in notification for this, see How to: Implement a Dependency Property
 
Back
Top Bottom