Image binding in WPF - c#

I have an Image control that is supposed to do a slide show.
Here are the binding I used to achieve this:
Binding mapBinding = new Binding();
mapBinding.Source = slideView;
mapBinding.Path = new PropertyPath("ImageDrawing");
sliderImage.SetBinding(System.Windows.Controls.Image.SourceProperty, mapBinding);
And a class SlideImage
public class SlideImage : INotifyPropertyChanged {
public ImageSource ImageDrawing{get;set;}
public void ChangeImage(){
// Load another image
// Update ImageDrawing
// Fire property changed event
}
public event PropertyChangedEventHandler PropertyChanged;
}
I found many examples on the net using the UpdateSourceTrigger to listen for data source changes. The only problem is the Image control does not have that property.
How do I hook up my sliderImage control to update on SlideImage.PropertyChanged?

It probably will update automatically, if you're actually calling PropertyChanged when calling the setter of ImageDrawing.
You aren't firing PropertyChanged for your ImageDrawing property in the code you've provided. Try this:
private ImageSource imageDrawing;
public ImageSource ImageDrawing
{
get { return imageDrawing; }
set
{
imageDrawing = value;
RaisePropertyChanged("ImageDrawing");
}
}
private void RaisePropertyChanged(string propertyName)
{
if(PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

Related

INotifyPropertyChanged does't work when field of property change internally

I try to binding textblock usercontrol with property of my class, but it only works at initial stage, I have implement IPropertyChnaged in my class.
In my class, _Feedbackpos (field of property) would change in background, I don't know how to solve this problem.
my class
public class TestControl : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyname)
{
if(PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
}
}
private double _Feedbackpos;
public double Feedbackpos
{
get
{
return _Feedbackpos;
}
set
{
_Feedbackpos = value;
NotifyPropertyChanged("Feedbackpos");
}
}
//it's a callback function, it would excute when detect feedback position of controller change
private void ReadFeedbackpos()
{
_Feedbackpos = Controller.Read();
}
}
application windows
TestControl TestDll = new TestControl();
Binding BindingTxtBlk = new Binding(){Source= TestDll, Path = new Property("Feedbackpos")};
FeedbackPosTxtBlk.Setbinding(Textblock.TextProperty,BindingTxtBlk);
Change the function ReadFeedbackpos() to
private void ReadFeedbackpos()
{
Feedbackpos = Controller.Read();
}
Otherwise NotifyPropertyChanged("Feedbackpos"); will never get called.

OnPropertyChanged for nested properties

I have the following class as my DataContext of my UserControl:
public class ModelBase<T> : INotifyPropertyChanged where T : class
{
public T Model { get; set; }
public void UpdateUI()
{
OnPropertyChanged(string.Empty);
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
I am setting Model as an arbitrary class the contains primitive types.
I seem to have the binding done correctly, because I can see that the properties are being populated as I change them in the UI.
But the problem is that when I change the properties from code behind, it won't update the view with it, even after calling UpdateUI(). I verified the properties in the DataContext of the UI (with WPF/XAML inspection software) and they have the correct values.
I believe it has something to do with the fact that it's a nested class inside the DataContext, because I tried adding properties to ModelBase to test it, and the bindings worked fine when I called UpdateUI().
I'm creating the controls/bindings and adding it to the UserControl in the code behind, I'm not sure if this would cause a problem:
var textBox = new TextBox();
// Setup Binding
var binding = new Binding
{
Source = myModelBase.Model,
Path = new PropertyPath(nameOfProperty),
Mode = BindingMode.TwoWay,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
};
BindingOperations.SetBinding(textBox, TextBox.TextProperty, binding);
myUserControl.Content.Children.Add(textBox);
To have TwoWay binding you will have to have the following:
backing fields
public properties in which the setters raise a property change
notification.
a Model that implements INotifyPropertyChanged interface or inherits
from a class that implements it
Here is a nice way to do it:
rewrite your ModelBase to be (based on Implementing INotifyPropertyChanged - does a better way exist?):
public class ModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
//make sure we fire the event only when newvalue!=oldvalue
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
}
and use it as
class Model:ModelBase{
//example for a property that is appropriate for 2 way bidning
private string _prop;
public string prop{
get{return _prop;}
set{SetField(ref _prop,value);}
}
}
if this is not sufficient please explain why it is not.
Update:based on what you want, you are doing it almost right your way but its just that you are not specifying the PropertyPath correctly, it should be "Model."+nameOfProperty and notice that you don't need to set the Source = myModelBase unless your container DataContext is not set to it.
So:
var binding = new Binding
{
Path = new PropertyPath("Model."+nameOfProperty),
Mode = BindingMode.Default,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
};
Or :
var binding = new Binding
{
Source = myModelBase,
Path = new PropertyPath("Model."+nameOfProperty),
Mode = BindingMode.Default,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
};
not sure if that will work but its probably the problem, otherwise your idea is fine.

How do I bind an object to a dynamically created label?

I am trying to bind but it doesn't seem to be working :/
my code:
void Binding(velocity Object, Label Output, string Field)
{
Binding newBinding = new Binding();
newBinding.Source = Object;
newBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
newBinding.Path = new PropertyPath(Field);
Output.SetBinding(Label.ContentProperty, newBinding);
}
Binding(newProjectile.CurrentVelocity, lbl_CurrentVelOutput, "Magnitude"); // how i call it
Thanks a bunch!
edit: i dont get an errror, its just that on the output the label doesnt change.
edit: i have tried looking for how to implement the INotifyChange interface and got something like this
public class velocity : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler Handler = PropertyChanged;
if (Handler != null)
{
Handler(this, new PropertyChangedEventArgs(name));
}
}
public double Velocity
{
get { return Magnitude; }
set
{
Magnitude = value;
OnPropertyChanged("10");
}
}
but i have no idea what i am doing.
Your binding should work just fine, but if you want changes to that Magnitude property to automatically show up in your view, then you'll have to let WPF know about those changes. That's where the INotifyProperty interface comes in, as it allows your code to let WPF known which properties have been changed:
// In C#, the common convention is to give classes CamelCased names:
public class Velocity : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
// Local variables and method arguments are also camelCased,
// but they start with a lower-case character:
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
// Properties with default getters and setters automatically get a 'backing field',
// but we can't use that because we need to call OnPropertyChanged, so we'll have to
// manually write out things. Normally, you'd give the backing field a name similar
// to the property, so it's obvious that they belong together:
private double _magnitude;
public double Magnitude
{
get { return _magnitude; }
set
{
_magnitude = value;
// Here, you need to pass in the *name* of the property that's being changed,
// so WPF knows which views it needs to update (WPF can fetch the new value
// by itself):
OnPropertyChanged("Magnitude");
}
}
}

Windows 8.1 UI not updating when MVVM property set is called by UI element

My problem is, that the UI isn't updating if they call the setter of the property which they binded to.
Here's a sample to make it clear:
Let's say I have a textbox binded to a property like this.
<TextBox PlaceholderText="Task Name..." FontSize="24"
Text="{Binding TaskName, Mode=TwoWay}" />
And this is my property:
public string TaskName
{
get
{
return _taskName;
}
set
{
_taskName = "something";
RaisePropertyChanged();
}
}
If I write something into the textbox then "something" should appear inside of it, after it loses focus, but there isn't any change. However, if I change the value of the property with code, like this:
TaskName = "something";
Then the change will appear on the UI as well.
Some further information.
This is how I implemented the INotifyPropertyChange interface:
public class ViewModelBase : INotifyPropertyChanged
{
public static Navigator NavigationService;
public static void SetNavigationService(Navigator service)
{
NavigationService = service;
}
protected void GoBack()
{
NavigationService.GoBack();
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
I really don't know why is it behave like this. I search for it for hours, but can't find anything.
in the setter of the property you need to call
RaisePropertyChanged(x => x.TaskName)

TextBlock data-bound to Singleton not updating in WPF

I apologize for the newbie question, but I am struggling with this problem. I have the following TextBlock defined:
<TextBlock Text="{Binding Source={x:Static local:DeviceManager.Instance},
Path=Player.CurrentArtist}"></TextBlock>
The DeviceManager is a singleton that functions as a facade for other classes. For example, Player is a property of type IPlayer which represents an music-playing application. I would like the TextBlock to display the artist that is currently playing, which is periodically updated in the Player.CurrentArtist property.
Unfortunately, I cannot get the TextBlock to update when the CurrentArtist property updates. Both the DeviceManager and the IPlayer implement INotifyPropertyChanged, but when I step through the application, the DeviceManager does not have an event handler attached to it.
Does anyone have a suggestion for how to update the text block while preserving the singleton-facade?
Here is the code for the INotifyPropertyChanged members in both the DeviceManager and the IPlayer subclass:
public sealed class DeviceManager : INotifyPropertyChanged
{
// Singleton members omitted
public IPlayer Player
{
get { return player; }
set
{
this.player = value;
player.PropertyChanged += new PropertyChangedEventHandler(device_PropertyChanged);
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void device_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(sender, e);
}
}
#endregion
}
class MediaPlayer : IPlayer
{
private string artist;
private string title;
public event PropertyChangedEventHandler PropertyChanged;
public void Play(string artist, string title)
{
this.artist = artist;
this.title = title;
OnPropertyChanged("Player:Song");
}
private void OnPropertyChanged(string p)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(p));
}
}
public string CurrentTitle
{
get { return title; }
}
public string CurrentArtist
{
get { return artist; }
}
}
The problem is that WPF is never notified of the value of the CurrentArtist property changing. You can either implement a private setter for the CurrentArtist property, which will trigger the PropertyChanged event, or trigger a PropertyChanged event for the CurrentArtist property in MediaPlayer.Play().
WPF only responds to PropertyChanged if the name you pass in (i.e. right now "Player:Song") is the same as the property you're bound to - change the PropertyChanged to "CurrentArtist" and you'll see it update properly.
You are not raising the PropertyChanged event, what you need is:
public sealed class DeviceManager : INotifyPropertyChanged
{
// Singleton members omitted
public IPlayer Player
{
get { return player; }
set
{
this.player = value;
OnPropertyChanged(this, new PropertyChangedEventArgs("Player"));
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(sender, e);
}
}
#endregion
}
How does the UI know when you change the Player property? From that code it does not look like it raises PropertyChanged to me. Can you post a complete working sample of the problem? Otherwise we're forced to just guess.

Categories