在Visual Studio设计器中隐藏WPF元素

29

我有一个 WPF 窗体,基本上看起来像这样:

<Window ...>
  <Grid>
    <DockPanel>
      [content shown during normal operation]
    </DockPanel>

    <Grid Background="#CCCC" Visibility="Hidden">
      [overlay grid which is only shown during special circumstances]
    </Grid>
  </Grid>
</Window>

这个覆盖网格会隐藏其他内容(即“普通内容”),只在特殊情况下显示出来(例如网络连接故障)。在运行程序时,这能够正常工作。

现在,在设计模式下,问题在于Visual Studio忽略了Visibility="Hidden"。通常情况下,这是有道理的(毕竟我想要编辑隐藏的UI元素),但在我的情况下很烦人,因为它阻止我在设计器中编辑DockPanel中的内容。

所以,我想做的事情就像这样:

<Grid Background="#CCCC" Visibility="Hidden" VS.ShowInDesigner="False">
  [overlay grid which is only shown during special circumstances]
</Grid>

但是,哀悼的是,并没有这样的属性,或者至少我不知道有。有什么想法吗?


1
我正在尝试以不同的方式解决问题,即我正在尝试弄清楚TabControl是如何实现这一点的。使用TabControl,您可以设置特定的选项卡被选中,但在设计器中,如果您将光标放置在其中一个选项卡的代码或设计器中的实际选项卡上,则会忽略此选项。而是显示设计时选择的选项卡。我认为Popup控件应该以相同的方式工作,我正在开发类似于Silverlight ChildWindow控件的东西,它将给我这种类型的设计时行为。 - jpierson
8个回答

81

从VS2012开始,您只需使用Blend命名空间的IsHidden属性:

  • 如果尚未存在,请添加xmlns:d =“http://schemas.microsoft.com/expression/blend/2008”
  • 将d:IsHidden =“true”放在您要仅在设计时隐藏的元素上

2
与Visibility属性不兼容。似乎Visibility具有优先级。我猜没有d:Visibility :( - Edgar
2
太棒了!在VS2017中,blend xmlns已经存在,但这个解决方案仍然不起作用(“属性'IsHidden'在blend中不存在...”)。我不得不寻找另一个信息,并发现,在包含xmlns:d="http://schemas.microsoft.com/expression/blend/2008"**的行之后,您需要包括另外两行:**xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" 然后IsHidden属性就可以完美地工作了。(抱歉,这里的格式有限) - Vit Kovalcik
1
在VS2017中,如果加入了上述的xmlns,IntelliSense便无法“看到”d:IsHidden属性,但是如果添加它则正如此答案所描述的那样起作用。 - Andrei Pana
1
@VitKovalcik,你的 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 缺少了 http:// - huang

11

很好的解决方案,我遇到了类似的问题并且同意有时是需要这样做的。下面是一个小更新,可以在设计时编辑该值以开启或关闭IsHidden。我还应用了ScaleTransform而不是设置Width和Height来降低屏幕图像畸变(如果控件手柄等被显示)并避免冲突(假设要隐藏的控件已经有了Width和Height属性设置,即假定该控件没有LayoutTransform)。

Public Class DesignModeTool

  Public Shared ReadOnly IsHiddenProperty As DependencyProperty = DependencyProperty.RegisterAttached( _
    "IsHidden", GetType(Boolean), GetType(DesignModeTool), _
    New FrameworkPropertyMetadata(False, New PropertyChangedCallback(AddressOf OnIsHiddenChanged)))

  Public Shared Sub SetIsHidden(ByVal element As FrameworkElement, ByVal value As Boolean)
    element.SetValue(IsHiddenProperty, value)
  End Sub

  Public Shared Function GetIsHidden(ByVal element As FrameworkElement) As Boolean
    Return DirectCast(element.GetValue(IsHiddenProperty), Boolean)
  End Function

  Private Shared Sub OnIsHiddenChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
    If System.ComponentModel.DesignerProperties.GetIsInDesignMode(d) AndAlso True.Equals(e.NewValue) Then
      With DirectCast(d, FrameworkElement)
        .LayoutTransform = New ScaleTransform(0.001, 0.001)
      End With
    ElseIf System.ComponentModel.DesignerProperties.GetIsInDesignMode(d) AndAlso False.Equals(e.NewValue) Then
      With DirectCast(d, FrameworkElement)
        .LayoutTransform = Nothing
      End With
    End If
  End Sub
End Class 

这非常有帮助。我喜欢这样的代码,可以从中学习。谢谢你。 - Mike Malter

9
很棒!我将其翻译成了C#,并更改了属性,使其更改为RenderTransform。
static class DesignModeTool
{
    public static readonly DependencyProperty IsHiddenProperty =
        DependencyProperty.RegisterAttached("IsHidden",
            typeof(bool),
            typeof(DesignModeTool),
            new FrameworkPropertyMetadata(false,
                new PropertyChangedCallback(OnIsHiddenChanged)));

    public static void SetIsHidden(FrameworkElement element, bool value)
    {
        element.SetValue(IsHiddenProperty, value);
    }

    public static bool GetIsHidden(FrameworkElement element)
    {
        return (bool)element.GetValue(IsHiddenProperty);
    }

    private static void OnIsHiddenChanged(DependencyObject d,
                                          DependencyPropertyChangedEventArgs e)
    {
        if (!DesignerProperties.GetIsInDesignMode(d)) return;
        var element = (FrameworkElement)d;
        element.RenderTransform = (bool)e.NewValue
           ? new ScaleTransform(0, 0)
           : null;
    }
}

8

由于没有内置的方法来实现这一点,我决定自己实现一个解决方案,使用附加属性非常容易实现:

Public Class DesignModeTool
    Public Shared ReadOnly IsHiddenProperty As DependencyProperty = DependencyProperty.RegisterAttached( _
        "IsHidden", GetType(Boolean), GetType(DesignModeTool), _
        New FrameworkPropertyMetadata(False, New PropertyChangedCallback(AddressOf OnIsHiddenChanged)))

    Public Shared Sub SetIsHidden(ByVal element As UIElement, ByVal value As Boolean)
        element.SetValue(IsHiddenProperty, value)
    End Sub

    Public Shared Function GetIsHidden(ByVal element As UIElement) As Boolean
        Return DirectCast(element.GetValue(IsHiddenProperty), Boolean)
    End Function

    Private Shared Sub OnIsHiddenChanged(ByVal d As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
        If System.ComponentModel.DesignerProperties.GetIsInDesignMode(d) AndAlso True.Equals(e.NewValue) Then
            With DirectCast(d, FrameworkElement)
                .Width = 0
                .Height = 0
            End With
        End If
    End Sub
End Class

声明命名空间后,可以像这样使用该功能:
<Grid ... local:DesignModeTool.IsHidden="True">
[stuff I don't want to be shown in the designer]
</Grid>

3

除了不使用设计师(真的,考虑一下这个建议),您可以将Grid的内容分离到单独的UserControl中。这样,您就可以在与可见性逻辑无关的情况下仅更新该UserControl


1
关于使用设计师:是的,我知道你的意思。我只使用设计师进行导航(单击控件,编辑器跳转到XAML代码)。然而,对于大型XAML文件来说,这是非常重要的功能。 - Heinzi

2

我在另一方面...讨厌VS 2012在设计师中隐藏WPF控件。我需要看到它们,因此我修改了gregsdennis的代码:

public class DesignModeTool
{
    public static readonly DependencyProperty IsHiddenProperty = DependencyProperty.RegisterAttached("IsHidden",   typeof(bool),  typeof(DesignModeTool),   new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnIsHiddenChanged)));

    public static void SetIsHidden(FrameworkElement element, bool value)
    {
        element.SetValue(IsHiddenProperty, value);
    }

    public static bool GetIsHidden(FrameworkElement element)
    {
        return (bool)element.GetValue(IsHiddenProperty);
    }

    private static void OnIsHiddenChanged(DependencyObject d,
                                          DependencyPropertyChangedEventArgs e)
    {
        if (!DesignerProperties.GetIsInDesignMode(d)) return;
        var element = (FrameworkElement)d;
        element.Visibility=Visibility.Visible;

    }
}

wpfClasses2:DesignModeTool.IsHidden="False"可以在设计模式下显示控件。


2

我最近遇到了类似的问题。

我正在使用一个矩形来在模态对话框执行期间隐藏主窗口。我已经将可见性数据绑定,但是这个矩形使设计师无法使用。我把 Z 轴索引设置为一次性数据绑定,并且回退值低于我想要隐藏的窗口。当应用程序启动时,矩形的 Z 轴索引被绑定到比窗口更高的值。


2

可能对其他人有用。如果您想在VS2022的设计模式下隐藏元素:

d:Visibility="Hidden"

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