ContentPresenter Grid内部的可见性绑定不起作用?

时间:2013-12-04 14:18:53

标签: wpf grid converter visibility contentpresenter

我有一个以下网格:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    ...
    <ContentPresenter Grid.Row="1" Content="{Binding Path=PredictiveWorkspace}"
                      Visibility="{Binding Path=ShowPredictiveWorkspace, 
                      Converter={StaticResource boolToVisibility}}"/>
    <ContentPresenter Grid.Row="1" Content="{Binding Path=M2Workspace}"
                      Visibility="{Binding Path=ShowStandardWorkspace, 
                      Converter={StaticResource boolToVisibility}}"/>
    ...
</Grid>

这两个ContentPresenters具有相同的Grid.Row,因为其中只有一个应该同时可见。 我关注了boolToVisibility转换器:

[ValueConversion(typeof(bool), typeof(System.Windows.Visibility))]
public class BoolToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if ((bool)value)
        {
            return System.Windows.Visibility.Visible;
        }
        else
            return System.Windows.Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return null;
    }
}

问题在于:ContentPresenters都可见!我还注意到应用程序只读取ShowPredictiveWorkspace属性。永远不会调用在ShowStandardWorkspace getter上设置的断点。 我想这是一个愚蠢的错误,但我真的无法找到它。

编辑:

public bool ShowStandardWorkspace
    {
        get { return this._showStandardWorkspace; }
        set
        {
            this._showStandardWorkspace = value;
            this.OnPropertyChanged(() => this.ShowStandardWorkspace);
        }
    }

4 个答案:

答案 0 :(得分:9)

这是因为它无法将可见性与ContentPresenter元素上的转换器绑定。

如果将ContentPresenter更改为ContentControl,则可以将visibility属性与转换器绑定,然后您不必将其嵌套在另一个元素中。

这显然是因为ContentPresenter是一个轻量级元素,意在ControlTemplate中使用。

From MSDN(突出显示):

  

您通常在a的ControlTemplate中使用ContentPresenter   ContentControl 指定要添加内容的位置。一切   ContentControl类型默认具有ContentPresenter   控件模板。

     

当ContentPresenter对象在。时   ContentControl的ControlTemplate,Content,ContentTemplate和   ContentTemplateSelector属性从中获取它们的值   ContentControl的相同名称的属性。你可以拥有   ContentPresenter属性从中获取这些属性的值   通过设置ContentSource,模板化父级的其他属性   财产或与他们绑定。

答案 1 :(得分:3)

我一直在搜索很多,而且我做了一些测试,我很确定你无法控制contentpresenter的可见性。另外 - 如果在显示视图时由ContentPresenter呈现的ViewModel为null,则它甚至不会使用boolToVisibilityConverter来读取属性。

我做了一个简单的解决方法 - 我将ContentPresenter置于Grid(显然可以使用其他类型的容器)并将Visibility的{​​{1}}绑定到布尔值属性。它运作得很好。

答案 2 :(得分:1)

您应该使用AncestorType。使用ContentPresenter时,DataContext不相同,但您可以在Visual Tree中向上导航以查找它。在你的情况下:

Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type Grid}}, Path=ShowStandardWorkspace}"

默认情况下,Grid是第一个祖先,并使用其DataContext。如果您需要第二个,第三个等祖先,请使用AncestorLevel属性int。 我认为转换器很好。

答案 3 :(得分:0)

可能的错误来源:

  • 拼写错误ShowStandardWorkspace
  • 在属性设置器中未引发OnPropertyChanged(“ShowStandardWorkspace”)
  • ShowStandardWorkspace属性不能设置为false
  • 第二个ContentPresenter的错误DataContext