i'm not really sure how to explain this... i'm going to put the code in psuedo code for easy reading
pretty much I want a label to change it's text when a bool variable of a class changes... i'm not sure what I need to use since i'm using WPF and the class can't just change the label i don't think?
do i need some sort of event? or a WPF event? thanks for any help
public MainWindow()
{
SomeClass temp = new SomeClass();
void ButtonClick(sender, EventArgs e)
{
if (temp.Authenticate)
label.Content = "AUTHENTICATED";
}
}
public SomeClass
{
bool _authenticated;
public bool Authenticate()
{
//send UDP msg
//wait for UDP msg for authentication
//return true or false accordingly
}
}
Another WPF approach other than BradledDotNet answer is to use triggers. This will be purely XAML based without converter code.
XAML:
<Label>
<Label.Style>
<Style TargetType="Label">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsAuthenticated}" Value="True">
<Setter Property="Content" Value="Authenticated" />
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
Same rule applies as mentioned by BradledDotNet, ViewModel should be attached and "IsAuthenticated" property should raise the PropertyChanged event.
-- Add some boilerplate code as suggested by Gayot Fow --
View Code Behind:
For simplicity I will just set the DataContext of the view in code behind. For a better design you can use ViewModelLocator as explained here.
public partial class SampleWindow : Window
{
SampleModel _model = new SampleModel();
public SampleWindow() {
InitializeComponent();
DataContext = _model; // attach the model/viewmodel to DataContext for binding in XAML
}
}
Example Model (it should really be ViewModel):
The main point here is the attached model/viewmodel has to implement INotifyPropertyChanged.
public class SampleModel : INotifyPropertyChanged
{
bool _isAuthenticated = false;
public bool IsAuthenticated {
get { return _isAuthenticated; }
set {
if (_isAuthenticated != value) {
_isAuthenticated = value;
OnPropertyChanged("IsAuthenticated"); // raising this event is key to have binding working properly
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propName) {
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}
Since we are using WPF, I would use a binding and converter to accomplish this:
<Page.Resources>
<local:BoolToAuthenticationStringConverter x:Key="BoolToAuthenticationStringConverter"/>
</Page>
<Label Content="{Binding Path=IsAuthenticated, Converter={StaticResource BoolToAuthenticationStringConverter}"/>
Then a converter that looks like:
public class BoolToAuthenticationStringConverter : IValueConverter
{
public object Convert (...)
{
if ((bool)value)
return "Authenticated!";
else
return "Not Authenticated!";
}
public object ConvertBack (...)
{
//We don't care about this one for this converter
throw new NotImplementedException();
}
}
In our XAML, we declare the converter in the resources section, then use it as the "Converter" option of the binding for "Content". In the code, we cast value
to a bool (IsAuthenticated
is assumed to be a bool in your ViewModel), and return an appropriate string. Make sure your ViewModel implements INotifyPropertyChanged
and that IsAuthenticated
raises the PropertyChanged
event for this to work!
Note: Since you won't be changing the Label
via the UI, you don't need to worry about ConvertBack
. You could set the mode to OneWay
to make sure that it never gets called though.
Granted, this is very specific to this scenario. We could make a generic one:
<Label Content="{Binding Path=IsAuthenticated, Converter={StaticResource BoolDecisionToStringConverter}, ConverterParameter='Authenticated;Not Authenticated'}"/>
Then a converter that looks like:
public class BoolDecisionToStringConverter : IValueConverter
{
public object Convert (...)
{
string[] args = String.Split((String)parameter, ';');
if ((bool)value)
return args[0];
else
return args[1];
}
public object ConvertBack (...)
{
//We don't care about this one for this converter
throw new NotImplementedException();
}
}
Yes, you need an event.
Consider a sample like this:
public SomeClass {
public event EventHandler<EventArgs> AuthenticateEvent;
boolean isAuthenticated;
public bool Authenticate()
{
// Do things
isAuthenticated = true;
AuthenticateEvent(this, new EventArgs());
}
}
public MainWindow()
{
SomeClass temp = new SomeClass();
public MainWindow(){
temp.AuthenticateEvent+= OnAuthentication;
temp.Authenticate();
}
private void OnAuthentication(object sender, EventArgs e){
Dispatcher.Invoke(() => {
label.Content = "AUTHENTICATED";
});
}
}
Now whenever temp
fires the Authenticate
event, it will change your label.