What you are trying to do is to update the Visibility
property of the Grid
using a Setter
and maintain the binding at the same time. The problem is that binding is overwritten by the Setter
!
When you use Xaml Setters you set properties the same way as you set them in the tag, so when you write:
<Setter TargetName="RedGrid" Property="Visibility" Value="Collapsed"/>
It acts the same way as if you've written:
<Grid x:Name="RedGrid" Visibility="Collapsed">
Notice that the binding Visibility="{Binding Path=IsVisible"}
has been overwritten by the value Visibility="Collapsed"
and will no longer work.
But Why?
The way that TwoWay
binding works can be found inside the controls themselves. When you work with DependencyProperties by default you set them using SetValue()
method, which sets the property's value and overwrites any binding in place.
However, in controls like TextBox
or CheckBox
that take in user input, when the user interacts with them, properties like TextBox.Text
and CheckBox.IsChecked
are being set by the method SetCurrentValue()
which like the documentation says:
The SetCurrentValue method changes the effective value of the property, but existing triggers, data bindings, and styles will continue to work.
You can review this question for more information about the differences between SetValue()
and SetCurrentVaule()
methods.
What to do:
In your case, I think that you can add a GridOpacity
property to the view model, and instead of changing the Visibility
in Xaml using a Setter
, you can change the view model's IsVisible
property directly when you set the GridOpacity
property.
Here is a sample code of the view model:
private Visibility _isVisible;
public Visibility IsVisible
{
get => _isVisible;
set
{
if (_isVisible == value)
{
return;
}
_isVisible = value;
RaisePropertyChanged(nameof(IsVisible));
}
}
private double _gridOpacity;
public double GridOpacity
{
get => _gridOpacity;
set
{
if (_gridOpacity == value)
{
return;
}
_gridOpacity = value;
RaisePropertyChanged(nameof(GridOpacity));
// Change the visibility of the grid when opacity hits 0.
if (value == 0)
{
IsVisible = Visibility.Collapsed;
}
else
{
// Change it back.
IsVisible = Visibility.Visible;
}
}
}
And here is the Xaml:
<Grid x:Name="RedGrid" Visibility="{Binding IsVisible}" Opacity="{Binding GridOpacity}">
...
</Grid>