WPF:通过字符串内容绑定可见性

18

好的,这是我的XAML代码:

<TextBlock Text="{Binding Path=InstanceName}"></TextBlock>

如果 InstanceName 是 null 或空字符串,则我希望 Visibility="Collapsed"。否则,我希望 Visibility="Visible"。我该怎么做?

5个回答

50

您可以使用 ValueConverter:

<TextBlock 
     Visibility="{Binding InstanceName, Converter={local:StringNullOrEmptyToVisibilityConverter}}" 
     Text="{Binding InstanceName}"/>

使用以下代码:

public class StringNullOrEmptyToVisibilityConverter : System.Windows.Markup.MarkupExtension, IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return string.IsNullOrEmpty(value as string) 
            ? Visibility.Collapsed : Visibility.Visible;
    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return null;
    }
    public override object ProvideValue(IServiceProvider serviceProvider)
    {            
        return this;
    }
}

我能看出来那个方法可行,但是那会变得非常乏味。我不禁想,一定有更好的方法。 - Jonathan Allen
6
你认为最烦琐的部分是什么?你认为分别设置可见性和文本会变得繁琐吗?或者总体而言,你是否认为值转换器会很繁琐?我会进行一些修改,将Visibility属性与RelativeSource绑定到Self,Path=Name,这样就不必重复“InstanceName”!除此之外,我没看到还有其他繁琐的地方了。(你可以编写自己的MarkupExtensions甚至是行为来完成这个任务,但我认为这有点过头了,使用一个ValueConverter就足够了。) - Markus Hütter

3

如果您在(数据)模板内部,可以使用触发器

否则,MVVM模式值转换器将对您有所帮助。


触发器和ValueConverter都不太容易进行测试。 - Peter Lillevold
2
它们中没有一个是“可测试的”,因为唯一真正的测试方法是视觉检查结果是否达到了期望的效果。 - Jonathan Allen

2
通过在ViewModel中添加一个额外的属性,您可以将Visibility属性绑定到该属性上:
public class ViewModel
{
   public string InstanceName {...}
   public Visibility InstanceVisibility 
   { 
      get 
      {
           return String.IsNullOrEmpty(InstanceName) ? Visibility.Collapsed : Visibility.Visible;
      }
}

1
我不喜欢那个。这个模型需要被多个视图共享,但是这种行为只需要针对这一个视图。 - Jonathan Allen
3
在我的看法中,视图和视图模型是一对一的关系。如果你有多个视图共享某些常见功能,可以提取这些共同部分并将其放入一个共同的视图模型超类中。 - Peter Lillevold
这听起来不对。我不熟悉“ViewModels”,但是使用经典的MVC模式,多个视图可以绑定到同一个模型实例上。这样,您可以在一个窗口中进行编辑并实时在另一个窗口中看到更新。 这段话的上下文可能需要更多信息才能确定最佳翻译。 - Jonathan Allen
4
关于MVC,你是正确的。但在MVVM中,ViewModel并不等同于Model。从缩写上看,Model-View-ViewModel,第一部分Model是我们的业务数据,View则指视图。而ViewModel则是两者之间的桥梁。ViewModel是“视图的模型”,即特定视图的Model定制版。是的,你可以有多个ViewModel针对同一个Model进行工作。在我看来,很少会有一个超级ViewModel服务多个视图。 - Peter Lillevold

1
<TextBlock Text="{Binding Path=InstanceName},FallbackValue={x:Null}"></TextBlock>

然后添加一个DataTrigger来检查值是否为null,并使用Setter更改可见性。这是我正在使用的简单方法。


0

好的,这与PyBinding接近:

<TextBlock Text="{Binding Path=InstanceName}" Visibility="{p:PyBinding BooleanToVisibility(IsNotNull($[.InstanceName]))}"  ></TextBlock>

我需要用一个意思是IsNotNullOrEmpty的东西来替换IsNotNull,但我正在接近。


以防万一:https://archive.codeplex.com/?p=pybinding - Keytrap

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