I have TextBox:
<TextBox DockPanel.Dock="Bottom"
FontFamily="Consolas"
Text="{Binding Path=Output}"
VerticalScrollBarVisibility="Visible"
HorizontalScrollBarVisibility="Auto"
AcceptsReturn="True"
AcceptsTab="True" />
To inside this TextBox I want to send some/add the message:
public string Output { get; set; }
public void WriteToOutput(string message)
{
Output += DateTime.Now.ToString("dd.MM HH:mm:ss") + " " + message + Environment.NewLine;
}
public void LoadExcelFile()
{
WriteToOutput("Start....")
//SOME CODE
WriteToOutput("End....")
}
Output should looks like:
Start...
End...
But the text it's not showing into TextBox. What is the reason?
Update: my MainViewModel.cs:
[AddINotifyPropertyChangedInterface]
public class MainViewModel
{
....
}
I'm using PropertyChanged.Fody
You're missing the INotifyPropertyChanged implementation.
A working example:
using System.ComponentModel;
public partial class MainWindow : Window, INotifyPropertyChanged
{
private string output;
public string Output
{
get { return output; }
set
{
output = value;
OnPropertyChanged(); // notify the GUI that something has changed
}
}
public MainWindow()
{
this.DataContext = this;
InitializeComponent();
this.Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
Output = "Hallo";
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(propertyName: propertyName));
}
}
}
The XAML code would look like this:
<TextBox Text="{Binding Output}"/>
As you can see, whenever the Output property changes, the PropertyChanged event will be called. Every GUI Element that is bound to that Property will know that something has changed.
Note: [CallerMemberName] automatically gets the name of the property the method has been called with. If you don't want to use it, remove it. You'd have to change the OnPropertyChanged call to OnPropertyChanged("Output");, though.
Related
I am working on a WPF application and I am trying to have text on the UI update after a button has been pressed. The data binding works for the initialization but when I try to change the text in the code after the button has been pressed, it does not update.
public class UpdateWindow : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _textStatus;
private readonly DeviceConnection deviceConnection = new DeviceConnection();
private readonly GetFile getFile = new GetFile();
public UpdateWindow()
{
TextStatus = "This will update the text";
}
//The button calls this WriteCommand function
public void WriteCommand()
{
TextStatus="The text on the UI should update here but it doesn't";
if (getFile.FindFile())
{
if (deviceConnection.CheckDeviceConnection())
{
//do something
}
else
{
//do something else
}
}
}
protected bool SetProperty<T>(ref T field, T newValue, [CallerMemberName] string propertyName = null)
{
if (!Equals(field, newValue))
{
field = newValue;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
return true;
}
return false;
}
public string TextStatus { get => _textStatus; set => SetProperty(ref _textStatus, value); }
}
And here is my XAML
<TextBlock x:Name="StatusText" Text="{Binding Path=TextStatus, UpdateSourceTrigger=PropertyChanged}" Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2" HorizontalAlignment="Center" />
I'm just not sure why it can initialize but not update.
I have some code which uses a form. The form is bound to my class, FormData. I have binding working well and updating my formData (local instance), but when I try to change the value of one of the variables in formData on button click/LostFocus trigger, it doesn't update.
Here's my relevant XAML:
<TextBox x:Name="friendly_name_textBox"
Style="{StaticResource TextErrorStyle}"
Text="{Binding
PrimaryUserName,
Mode=TwoWay,
ValidatesOnExceptions=True,
ValidatesOnDataErrors=True,
UpdateSourceTrigger=PropertyChanged,
NotifyOnValidationError=True}"
HorizontalAlignment="Left"
Margin="0,75,0,0"
TextWrapping="Wrap"
VerticalAlignment="Top"
Width="120"/>`
The button trigger (which does get run):
private void Button_Click(object sender, RoutedEventArgs e)
{
formData.PrimaryUserName = "TEST";
}
And my FormData code:
public string PrimaryUserName
{
get
{
return primaryUserNameValue;
}
set
{
if(primaryUserNameValue != value)
{
primaryUserNameValue = value;
}
}
}
You need to implement the INotifyPropertyChanged interface and raise the PropertyChanged event in your formData class:
public class formData : INotifyPropertyChanged
{
private string primaryUserNameValue;
public string PrimaryUserName
{
get
{
return primaryUserNameValue;
}
set
{
if (primaryUserNameValue != value)
{
primaryUserNameValue = value;
NotifyPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Your Class needs to implement INotifyPropertyChanged, so that the target knows if the source property changes:
https://learn.microsoft.com/en-us/dotnet/framework/wpf/data/how-to-implement-property-change-notification
It's really easy, please have a look at the documentation and adjust your code accordingly. Your Property would have to look like this:
public string PrimaryUserName
{
get
{
return primaryUserNameValue;
}
set
{
if(primaryUserNameValue != value)
{
primaryUserNameValue = value;
OnPropertyChanged("PrimaryUserName");
}
}
}
But you also need the event and onPropertyChanged function to make it work.
Happy Coding!
I am using the mahapps metro app to make a gui in wpf. I have used the code
<Controls:Badged Badge="{Binding Path=BadgeValue}">
<!-- Control to wrap goes here -->
<Button Content="Notifications" />
</Controls:Badged>
Say, if i want to update the 'BadgeValue' in the notifications callback, how do i go about doing this? plz help..
You set the BadgeValue source property that you bind to in your XAML and raise the PropertyChanged event, just like you would update any other data-bound property.
Here is an example for you:
View Model:
public class ViewModel : INotifyPropertyChanged
{
private string _badgeValue;
public string BadgeValue
{
get { return _badgeValue; }
set { _badgeValue = value; NotifyPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
MainWindow.xaml.cs:
public partial class MainWindow : Window
{
ViewModel viewModel = new ViewModel();
public MainWindow()
{
InitializeComponent();
DataContext = viewModel;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
viewModel.BadgeValue = "new value...";
}
}
MainWindow.xaml:
<Controls:Badged Badge="{Binding Path=BadgeValue}">
<Button Content="Notifications" />
</Controls:Badged>
<Button Content="Update" Click="Button_Click" />
this my xml code
<TextBlock Grid.Column="0" Tag="{Binding id,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Text="{Binding Name,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
this is my model
public string _Name;
public string Name
{
get { return _Name; }
set { _Name = value; RaisePropertyChanged("Name"); }
}
when i set value to these two propertie ie. to id and Name
but its not notifying to Name ...
Simple Databinding Example with Updates. You can use this as a reference to get you started :)
public partial class MainWindow : Window, INotifyPropertyChanged
{
// implement the INotify
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
private string _mytext;
public String MyText
{
get { return _mytext; }
set { _mytext = value; NotifyPropertyChanged("MyText"); }
}
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
this.DataContext = this; // set the datacontext to itself :)
MyText = "Change Me";
}
}
<TextBlock Text="{Binding MyText}" Foreground="White" Background="Black"></TextBlock>
I have a simple object (which is globally initiated in App.xaml.cs):
public class now_playing : INotifyPropertyChanged
{
// notify
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string p)
{
Debug.WriteLine(p + ": notify propertychanged");
PropertyChangedEventHandler handler = PropertyChanged;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(p));
}
// artist
public string artist
{
get
{
return _artist;
}
set
{
_artist = value;
NotifyPropertyChanged("artist");
}
}
private string _artist;
// album
public string album
{
get
{
return _album;
}
set
{
_album = value;
NotifyPropertyChanged("album");
}
}
private string _album;
// track title
public string tracktitle
{
get
{
return _tracktitle;
}
set
{
_tracktitle = value;
NotifyPropertyChanged("tracktitle");
}
}
private string _tracktitle;
}
Whenever I change the values, the class does notify (I see the debug).
So I guess the problems lies in my XAML or the code behind.
Page code:
public sealed partial class nowplaying : Page
{
// artistdata
public string artist { get { return App.nowplaying.artist; } }
// albumdata
public string album { get { return App.nowplaying.album; } }
// trackdata
public string tracktitle { get { return App.nowplaying.tracktitle; } }
public nowplaying()
{
this.InitializeComponent();
this.DataContext = this;
}
}
XAML:
<Grid Margin="50">
<TextBlock Text="{Binding tracktitle}" Foreground="White" FontSize="40"/>
<TextBlock Foreground="#dcdcdc" FontSize="20" Margin="0,50,0,0">
<Run Text="{Binding artist}"/>
<Run Text=" - "/>
<Run Text="{Binding album}"/>
</TextBlock>
</Grid>
Why does the UI not update when I change values?
Stack trace:
Music.exe!Music.App.InitializeComponent.AnonymousMethod__6(object sender = {Music.App}, Windows.UI.Xaml.UnhandledExceptionEventArgs e = {Windows.UI.Xaml.UnhandledExceptionEventArgs}) Line 50 C#
Music.exe!play_music.MessageReceivedFromBackground(object sender = null, Windows.Media.Playback.MediaPlayerDataReceivedEventArgs e = {Windows.Media.Playback.MediaPlayerDataReceivedEventArgs}) Line 57 C#
UPDATE: problem solved! I had to use a dispatcher when calling the propertychanged event:
CoreDispatcher dispatcher = CoreWindow.GetForCurrentThread().Dispatcher;
if (PropertyChanged != null)
{
await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
this.PropertyChanged(this, new PropertyChangedEventArgs(p));
});
}
You "loose" the change notification in the properties in the Page as these properties do not have any change notifiaction.
Try using now_playing directly:
public sealed partial class nowplaying : Page
{
public now_playing NowPlaying { get { return App.nowplaying; } }
public nowplaying()
{
this.InitializeComponent();
this.DataContext = this;
}
}
and
<Run Text="{Binding NowPlaying.artist}"/>
Otherwise you need to implement INotifiyPropertyChanged in nowplaying and forward the events from now_playing.
You actually binding to artist, album and tracktitle Of nowplaying class which does implement INotifyPropertyChanged