Binding not updating from INotifyPropertyChanged class - c#

I am new to WPF. I have binded the source class properties to target controls successfully. But whenever the properties value changes the UI controls not reflecting the updated data. Please help
WPF Code:
<Label Name="Panel_ch1Mode" Content="{Binding Path=Mode, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" FontFamily="Roboto Regular" FontSize="16" Foreground="#FFFFFF"/>
My Class:
public class ClassName: INotifyPropertyChanged
{
//Auto Refresh
private string mode;
public string Mode
{
get
{
return this.mode;
}
set
{
this.mode = value;
NotifyPropertyChanged("Mode");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

Try this: Just remove from xaml the UpdateSourceTrigger=PropertyChanged, Mode=TwoWay. )
Improve your implementation of INotifyPropertyChanged linke this:
private void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}

In code behind please check if the ViewModel is "wired" to the View:
public YourView()
{
InitializeComponent();
DataContext = new ClassName();
}
You have to keep in mind that a binding is always related to DataContext.

Related

PropertyChanged remains null

I have following textbox binding:
XAML:
<TextBlock x:Name="Auslastungskapazität1" Text="{Binding Kapazität, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Foreground="Black" HorizontalAlignment="Center" Margin="0,5,5,5" FontSize="16" ></TextBlock>
MainViewModel Class:
class MainViewModel: ZuliefererStandortListe, IDropTarget, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public int Kapazität {
get { return _kapazität1Ausgelastet; }
set {
if (this._kapazität1Ausgelastet != value)
_kapazität1Ausgelastet = value;
OnPropertyChanged("Kapazität");
}
}
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
DataContext is the in the MainWindow Constructor as
Kapazität.DataContext = new MainViewModel();
If I change Kapazität the int get changed and the OnPropertyChanged() method gets called. However "PropertyChanged" remains null and therefore the Textbox Binding doesn't get updated.
Either set the DataContext of the TextBox itself:
Auslastungskapazität1.DataContext = new MainViewModel();
...or of any of its parent elements, such as for example the window:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel();
}
}

WPF TextBlock binding to ResourceDictionary in mutilingual

I have a mutilingual wpf project. I am using ResourceDictionary to do this. For static TextBlock I can change the Text language by:
<TextBlock Text="{Binding Sample, Source={StaticResource Resources}}" />
BUT how should I change a dynamic TextBlock Text. It seems impossible to do it in this way:
<TextBlock Text="{Binding Sample}
And in the code behind:
Sample = Resources.SampleText;
If this is impossible. Is there any other options? Thanks in advance!
The class where the Sample property is define should implement the INotifyPropertyChanged interface and raise change notifications:
public class Translations : INotifyPropertyChanged
{
private string _sample;
public string Sample
{
get { return _sample; }
set { _sample = value; OnPropertyChanged("Sample"); }
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Only then you will be able to update the TextBlock dynamically by simply setting the Sample source property to a new string value.

Observable collection not reacting to it's collecion

My ListBox doesn't react to my ObservableCollection.
This is the ListBox I am talking about.
<ListBox x:Name="CreateFieldsList"
HorizontalAlignment="Left"
Height="218"
VerticalAlignment="Top"
Width="244"
Margin="0,86,0,0"
BorderBrush="#FFB9B9B9">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="4"
Width="215"
Height="32.96"
Background="White">
<TextBlock Text="{Binding Name}"
FontWeight="Normal"
FontSize="18.667"
Padding="8,3,0,0" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In my MainWindow, I prepare the data binding like this
private ObservableCollection<FieldListItem> _fieldItems;
public MainWindow()
{
InitializeComponent();
_fieldItems = new ObservableCollection<FieldListItem>();
CreateFieldsList.ItemSource = _fieldItems;
}
A FieldListItem is following
public class FieldListItem : ViewItem
{
private Field _field;
public string Name
{
get { return _field.Name; }
}
public string Value
{
get { return _field.Value; }
}
public FieldListItem(Field f)
{
_field = f;
}
}
and finally the ViewItem
public class ViewItem : INotifyPropertyChanged
{
private event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged([CallerMemberName] string caller = "")
{
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(caller));
}
//The interface forces me to implement this. Why?
event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
{
add { }
remove { }
}
}
I don't know why this isn't working. Could you please help?
The INotifyPropertyChanged interface needs you to implement an event. Your event implementation does not work because registrations and deregistrations are ignored because the add and remove blocks are empty.
Implement the event without add and remove:
public class ViewItem : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged([CallerMemberName] string caller = "")
{
var copy = PropertyChanged;
if (copy != null)
copy(this, new PropertyChangedEventArgs(caller));
}
}

INotifyPropertyChanged and DataBinding

I'm making a test application to handle a CardReader, I have an enum with the states of the CardReader and a XAML window with a TextBlock, i want that when the state change the onPropertyChanged change the TextBlock with the name of the state.
Here is part of my code:
public class CardControler : INotifyPropertyChanged
{
private CardState state;
public CardState State
{
get { return state; }
set
{
if (state != value)
{
state = value;
OnPropertyChanged(state);
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(CardState state)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(state.ToString()));
}
}
......................................................................
public partial class CardReader : Window
{
public CardControler control { get; set; }
public CardReader(int port)
{
this.DataContext = control;
this.port = port;
InitializeComponent();
ScreenWrite(CardState.Initializing);
Thread thread = new Thread(new ThreadStart(asincControlCreate));
thread.Start();
}
And in the xaml
<TextBlock Name="Screen" Text="{Binding Path=control.state}></TextBlock>
I hope i explained my self correctly and somebody can help me.
Thanks in advance
The following line is incorrect as you should pass propertyName as a parameter instead of state.ToString():
PropertyChanged(this, new PropertyChangedEventArgs(state.ToString()));
So your code should look something like:
public CardState State
{
get { return state; }
set
{
if (state != value)
{
state = value;
OnPropertyChanged("State");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
In addition to this keep in mind that xaml is case sensitive so {Binding State} is not the same as {Binding state}.
I think the problem is that you are raising the OnPropertyChanged with the value that is changing, rather than the actual property name (i.e. "State" in this case).
protected void OnPropertyChanged(String propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
I suspect you also need to change your XAML to bind to the appropriate property (note, the property name is State not state - the XAML will be case sensitive):
<TextBlock Name="Screen" Text="{Binding Path=control.State}></TextBlock>
You should pass the name of the property that changed, not its value:
PropertyChanged(this, new PropertyChangedEventArgs("State"));
The case of the property in your binding needs to match the public property (State, not state):
<TextBlock Name="Screen" Text="{Binding Path=control.State}></TextBlock>
You have alread set the datacontext of the page to control so your binding
<TextBlock Name="Screen" Text="{Binding Path=control.state}></TextBlock>
will be wrong.
your binding should be
<TextBlock Name="Screen" Text="{Binding Path=State}></TextBlock>
Instead of
public CardControler control { get; set; }
try this:
public CardControler control = new CardControler();
your OnPopertyChanged Event Call is wrong , you have to pass Property name as the argumeny. you can add the code i added below. that way you can avoid passing the parameter name altogether.
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}

WPF TextBox Bind

I have a class called VoucherEntity, includes a Property named "Customer", a object of Class CustomerEntity, so I have bellow code,
<TextBox Height="23" IsReadOnly="False" HorizontalAlignment="Stretch" Margin="124,48,174,0" Name="txt_customer" VerticalAlignment="Top" Text="{Binding Path=Customer.Name}" />
in .cs file, I have bellow code
_voucher = new VoucherEntity();
this.DataContext = _voucher;
it means, at first, the Customer property is null, after clicked a button, I will give Customer property of _voucher a CustomerEntity object, then I hope the TextBox can display it immediately, but failed, what should I do?
If you want to except changes in your view you should notify the view about the changes.
So just implement the INotifyPropertyChanged interface in the VoucherEntity class and fire the PropertyChanged event after you set the Customer prop
public class VoucherEntity: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void FirePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
private CustomerEntity _customer;
public CustomerEntity Customer
{
get {return _customer;}
set
{
if (_customer != value)
{
_customer= value;
FirePropertyChanged("Customer");
}
}
}
}

Categories