MVVM - hiding a control when bound property is not

2019-01-19 11:56发布

问题:

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...

回答1:

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
}