1
votes

I want to change the visibility of a Grid depending on whether the value of some TextBoxes is larger than other TextBoxes. I'm using MVVM and have the following code:

XAML

<UserControl.Resources>
    <BooleanToVisibilityConverter x:Key="BoolToVis"/>
</UserControl.Resources>

<Grid x:Name="TimeError" Visibility="{Binding Path=IsTimeValid, Converter={StaticResource BoolToVis}}">
    <TextBlock Text="Incorrect value"/>
</Grid>

<TextBox x:Name="TotalStarthh" MaxLength="2" FontSize="16" Width="28" Text="{Binding TotalStarthh}"/>
<more TextBoxes/>

In the ViewModel I parse the textBoxes to an integer value and calculate the total time.

private string _TotalStarthh;
public string TotalStarthh
{
    get { return _TotalStarthh; }
    set { _TotalStarthh = value; NotifyPropertyChanged(); }
}
//The same for the other TextBoxes.

public int Totalstart()
{
    int.TryParse(TotalStarthh, out int TShh);
    int.TryParse(TotalStartmm, out int TSmm);
    int.TryParse(TotalStartss, out int TSss);
    //calculating hours:mins:sec to total seconds
    //This can be over 24 hours so datetime is not used
    int Totalstart = TShh * 3600 + TSmm * 60 + TSss;
    return Totalstart;
}

public int Totalend()
{
    int.TryParse(TotalEndhh, out int TEhh);
    int.TryParse(TotalEndmm, out int TEmm);
    int.TryParse(TotalEndss, out int TEss);
    //calculating hours:mins:sec to total seconds
    //This can be over 24 hours so datetime is not used
    int Totalend = TEhh * 3600 + TEmm * 60 + TEss;
    return Totalend;
}

// validate that start time is lower than end time.
public bool IsTimeValid
{
    get { return (Totalstart > Totalend); }
    set { NotifyPropertyChanged(); }
}

But this doesn't update the Visibility of the Grid. Am I doing the NotifyPropertyChanged incorrectly? I'm fairly new to mvvm and am still trying to grasp it. Thanks in advance.

2
you IsTimeValid property setter is never called. at least not in this code snippet. and there's the important NotifiyPropertyChanged that should happen..Jurica Smircic
To trigger the Converter you have to raise the NotifyPropertyChanged() of your IsTimeValid. So you could add NotifyPropertyChanged(nameof(IsTimeValid)); to the setter of your TotalStarthhMartin Backasch

2 Answers

3
votes

Your TotalStarthhproperty changes. And your UI is notified about that. But you never notified the UI that IsTimeValid might have changed, too.

You can either make IsTimeValid a normal property and set it to the boolean value you want every time a dependent property changes.

Or you can notify the UI that IsTimeValid has changed every time you change the two properties used. To explain how, we'd need to know what your NotifyPropertyChanged actually looks like.

If I'd have to take a guess, I'd say this might do the trick:

public string TotalStarthh
{
    get { return _TotalStarthh; }
    set 
    {
         _TotalStarthh = value;
         NotifyPropertyChanged(); // notifies the UI this property has changed
         NotifyPropertyChanged("IsTimeValid"); // notifies the UI IsTimeValid has changed 
    }
}
1
votes

You need to actually set the property to the new value before notifying. To achieve this, use a property with backing field.

private bool isTimeValid;
public bool IsTimeValid
{ 
  get { return (Totalstart > Totalend); }
  set
  {
    if(value != isTimeValid)
      {
        isTimeValid = value;
        NotifyPropertyChanged(nameof(IsTimeValid));
      }
   }
 }

Is strongly recommend to use Prism MVVM Framework though. It has a SetProperty function, which does all this work for you in a single line.