Search code examples
wpfxamlbindingmvvmvisibility

MVVM - hiding a control when bound property is not present


I was wondering if it is possible to hide a control on a view if the property to which the control is bound does not exist in the view model. For example, if I have the following:

<CheckBox Content="Quote"
          IsChecked="{Binding Path=IsQuoted}" />

Can I detect in XAML that the IsQuoted property does not exist on the view model, and simply hide the control in that instance.

I am essentially creating a wizard dialog that moves through a collection of view models, displaying the associated view for each one. For some of the view models in the collection, the "IsQuoted" property will be present, and for some not.

I would like to have a check box outside of these views that displays when the current view model has the property, and hides when the view model does not. All of the view models are derived from a common base class, but I would rather not clutter the base by adding a "ShowQuoted" property, etc.

Thoughts? And, thanks in advance...


Solution

  • Handle the case where it the value is present by using a converter which always returns Visibility.Visible. Handle the case where the value isn't present by specifying a fallback value. When the property isn't present the binding fails and receives the fallback value.

    <Page.DataContext>
        <Samples:OptionalPropertyViewModel/>
    </Page.DataContext>
    <Grid>
        <Grid.Resources>
            <Samples:AlwaysVisibleConverter x:Key="AlwaysVisibleConverter" />
        </Grid.Resources>
        <CheckBox 
            Content="Is quoted" 
            IsChecked="{Binding IsQuoted}"
            Visibility="{Binding IsQuoted, 
                         Converter={StaticResource AlwaysVisibleConverter}, 
                         FallbackValue=Collapsed}"
            />
    </Grid>
    
    public class OptionalPropertyViewModel
    {
        public bool IsQuoted { get; set; }
    }
    
    public class AlwaysVisibleConverter : IValueConverter
    {
        #region Implementation of IValueConverter
    
        public object Convert(object value, Type targetType,
                              object parameter, CultureInfo culture)
        {
            return Visibility.Visible;
        }
    
        public object ConvertBack(object value, Type targetType, 
                                  object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    
        #endregion
    }