0

I am very new to the data binding concept so excuse my question if it appears silly to you. This project is to learn some API functionality and WPF Data Binding along with it. But here is what problem I face when I try to show an icon on screen by setting Data Context of an Image element in WPF to property from a Class that stores the Path of the image used for displaying on screen. I have the following Image:

<Image x:Name="imgWeatherIcon" Grid.Column="2" HorizontalAlignment="Left" Margin="380,134,0,0" VerticalAlignment="Top"
           Width="90" Height="90" Source="{Binding ImgPath, UpdateSourceTrigger=PropertyChanged, Mode=OneWay, diag:PresentationTraceSources.TraceLevel=High}">
        <Image.DataContext>
            <c:ConditionsNow/>
        </Image.DataContext>
    </Image>

I bind the Source to a property so whenever this property changes I get the new icon/image displaying on screen. The problem is that this only works if DataContext is set on start of the program (Main Window) and I need it to be se inside a button click

Here is the code that works:

    public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        ApiHelper.InitializeApiClient();

        ConditionsNow conditionsObject = new();
        imgWeatherIcon.DataContext = conditionsObject;
        conditionsObject.ImgPath = @"https://developer.accuweather.com/sites/default/files/01-s.png";

    }

Note that 'imgWeatherIcon' is a Label where I display the icon/image and I am setting it's DataContext to the property 'ImgPath'. This is just to clarify the "imgWeatherIcon" since didn't include WPF code for it, but I can do if necessary.

If I do this every time I start up the application the datacontext is set properly to the ImgPath property and is updated in the UI.

But here is where I need it to work and can't figure out why doesn't it work:

    public ConditionsNow condObject = new();

    private async void BtnCity_Click(object sender, RoutedEventArgs e)
    {
        imgWeatherIcon.DataContext = condObject;
        condObject.ImgPath = @"G:\Visual Studio\Projects\Testing\AccuWeatherApp\accuweather-icon.jpg";
                    
    }

I know I lack knowledge of databinding and WPF, but would appreciate if someone give me a hint where the problem is. I did a lot of research about binding etc. but still can't figure this out. Btw if this is helpful for property 'ImgPath' I have INotifyPropertyChanged implemented to be able to track changes.

8
  • I understand what you mean and I tried this, but then does that mean I set the DataContext in Main Window (on start up), then just change the property "ImgPath"? If yes how would that work, since I am binding the data to object created from class ConditionsNow and I can't change the property of that instantiated object inside the button click. And this is where I have to change the "ImgPath" property because in the button click is the place where this happens. If the data is bound to object inside Main Window how can I change it inside the btn click? Commented Apr 2, 2021 at 7:53
  • Can you give me an example how would this work if I want to change the "ImgPath" property inside the button click? And the datacontext has already been set in the startup of the program. Because that is what I am trying to achieve, when clicking this button the data is taken from web source and "ImgPath" has to be changed to the proper image, but don't know how to change it without making an instance of the class that contains the property. And I can't use the one in Main window since it is totally different instance. Commented Apr 2, 2021 at 7:57
  • Resetting the DataContext has no effect because you are always setting it to the same value, i.e. condObject. That is not actually a change (and it is a bad idea anyway). Resetting the property to the same image path would also not work, because by default WPF caches images by the URI from which they were loaded (assuming that the Click handler is meant to reload a new image from the same file path). Besides that, it is pointless to set UpdateSourceTrigger=PropertyChanged on a OneWay Binding. Commented Apr 2, 2021 at 8:50
  • I was assuming that I bind the Image source to my "ImgPath" property in my class, then create an instance of that class and assign it to the datacontext so whenever I change the "ImgPath" property it takes the new value and reflects in the Image source so basically if I give it new image path (to a new image) it will show the new image. The whole idea of "ImgPath" was that I set the value of that property to the respective image I want to show and all images are taken from web page. And it makes sense that I shouldn't set the datacontext to the same value. Commented Apr 2, 2021 at 9:22
  • Then take a look at the answer... Commented Apr 2, 2021 at 9:23

1 Answer 1

0

You should not change the whole DataContext binding. You set the DataContext only once, and then only change the underlying properties that are bound to the UI. In your case, you should only change the ImgPath property. Therefore, remove the following from the button click event:

imgWeatherIcon.DataContext = condObject;

Make sure that ConditionsNow implement the INotifyPropertyChanged interface, so that you can call OnPropertyChanged() when changing the value of ImgPath. This is to ensure that the binding will cause the UI to change its presentation.

So your ConditionsNow class should have a form similar to the below:

public class ConditionsNow
{    
    private string _imgPath;
    public string ImgPath
    {
        get => _imgPath;
        set
        {
            _imgPath = value;
            OnPropertyChanged();
        }
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.