如果底层DataContext为空,如何隐藏控件?

24

我在视图模型中有一个对象,它有很多属性,其中一些偶尔会为空。我不想只在这些特定控件为空时显示某些控件。如果绑定为空,我应该如何隐藏控件?我考虑过使用某种转换器,但不知道如何确切地操作。有什么想法吗?

编辑:对不起,我应该提到这也将用于Silverlight,所以我不确定样式触发器是否有效...?

7个回答

40

这种方法更简单:

<CheckBox Visibility="{Binding Path=checkedField, TargetNullValue=Collapsed }">
当绑定属性checkedField为null时,Visibility将被设置为Collapsed。

这个是否应该在属性不再为 null 时重新显示复选框? - ChrisO
1
如果datacontext是MyType的一个对象(例如),并且它不为null,则会抛出异常: 无法将'MyApp.ViewModels.MyType'从类型'MyType'转换为类型'System.Windows.Visibility'在Path中使用的属性似乎应该以某种方式可转换为类型“Visibility”,但在一般情况下这几乎是不可能的。 - Califf
3
如果checkedField未被选中,但是obj(使用obj.checkedField)为空,则使用点语法来设置Path属性 <CheckBox Visibility="{Binding Path=., TargetNullValue=Collapsed }"> - Mikhail Poda
3
如果checkedField不是Visibility,则会抛出异常。 - Trisped

29

有一个像下面这样的转换器:

public sealed class NullToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value == null ? Visibility.Hidden: Visibility.Visible;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

现在,将属性与 Visibility 属性绑定。像这样:

<ListBox ItemsSource="{Binding Path=Squad}" 
         Visibility="{Binding Converter={StaticResource nullToVisibilityConverter}, 
                              Path=Squad}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <CheckBox Content="{Binding}" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

1
我相信那应该是可行的,但控件甚至没有调用转换器的Convert方法。那个不是null的控件调用了,但其他的没有。 - Harry
这个被接受的答案是不正确的。正如Harry所说,你必须使用TargetNullValue。 - Ronnie Overby
你在哪里实例化 nullToVisibilityConverter?我看到一个名为该名称的类,但它是大写的,而在XAML代码中的参数是小写的... - Konrad Viltersten

5
我也需要这个用于WindowsPhone WinRT应用程序。最终我使用了@PrinceAshitaka的转换器并根据类似问题的这个答案中所建议的在绑定中进行了小修改。
您应该使用FallbackValue=Collapsed以避免在数据上下文为空时精确显示控件。不确定为什么对我而言TargetNullValue=Collapsed没有起作用。
Visibility="{Binding Converter={StaticResource NullToVisibilityConverter}, FallbackValue=Collapsed}"

3
在Silverlight中,您可以使用下面的方法 - 将触发器添加到控件中:
<i:Interaction.Triggers>
    <core:DataTrigger Binding="{Binding SomeProperty}" Comparison="Equal" Value="{x:Null}">
        <core:ChangePropertyAction PropertyName="Visibility" Value="Collapsed" />
    </core:DataTrigger>
</i:Interaction.Triggers>

2
你可以使用 DataContextChanged 事件,当 DataContext 为空时,你可以将 Visibility 设置为 Collapsed
想了解更多,请点击 这里

但在这种情况下,您必须使用代码后端 - 这将与MVVM不兼容。 - Mikhail Poda
3
MVVM只是一种指导方针。在设计与该控件特定逻辑相关的代码时,使用code-behind是恰当的。 - Overlord Zurg

0

我需要这个,但是我无法在DataGridTemplateColumn内的DataTemplate中使其工作,所以这里是我成功实现的示例。

 <DataGridTemplateColumn>
     <DataGridTemplateColumn.CellTemplate>
         <DataTemplate>
            <ComboBox ItemsSource="{Binding Path=DataContext.AvailableHierarchies, 
                                            RelativeSource={RelativeSource FindAncestor, 
                                            AncestorType={x:Type ItemsControl}} }"
                      DisplayMemberPath="Name"
                      SelectedItem="{Binding Path=DataContext.SelectedHierarchy, 
                                             RelativeSource={RelativeSource FindAncestor, 
                                             AncestorType={x:Type ItemsControl}},UpdateSourceTrigger=PropertyChanged }"
                                      >
            <ComboBox.Style>
                <Style TargetType="ComboBox" BasedOn="{StaticResource {x:Type ComboBox}}">
                    <Style.Triggers>
                        <Trigger Property="ComboBox.ItemsSource" Value="{x:Null}">
                            <Setter Property="Visibility" Value="Collapsed"/>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </ComboBox.Style>
        </ComboBox>
    </DataTemplate>
</DataGridTemplateColumn.CellTemplate>

0
结合bugfixr的答案Phil的答案,我得到了以下代码(在WPF中):
<Button
    Name="Button1"
    Click="Button1_Click"
    Content="{Binding Path=ActiveSubJob.ButtonText[0]}"
    Visibility="{Binding Path=ActiveSubJob.ButtonText[0],
                         Converter={StaticResource AlwaysVisibleConverter},
                         FallbackValue=Collapsed,
                         TargetNullValue=Collapsed}"
    IsEnabled="{Binding Path=IsButton1Enabled}"
    />

不得不稍微调整Phil的AlwaysVisibleConverter的Convert方法,以使TargetNullValue正确工作。
public object? Convert(object? value, Type targetType, object parameter, CultureInfo culture)
{
    if (value is null)
    {
        return null;
    }
    return Visibility.Visible;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接