XAML 是不是有用于调试模式的条件编译器指令?
Posted
技术标签:
【中文标题】XAML 是不是有用于调试模式的条件编译器指令?【英文标题】:Does XAML have a conditional compiler directive for debug mode?XAML 是否有用于调试模式的条件编译器指令? 【发布时间】:2012-02-02 16:12:54 【问题描述】:对于 XAML 中的样式,我需要这样的东西:
<Application.Resources>
#if DEBUG
<Style TargetType="x:Type ToolTip">
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="FlowDirection" Value="LeftToRight"/>
</Style>
#else
<Style TargetType="x:Type ToolTip">
<Setter Property="FontFamily" Value="Tahoma"/>
<Setter Property="FlowDirection" Value="RightToLeft"/>
</Style>
#endif
</Application.Resources>
【问题讨论】:
我需要在调试模式下有不同的风格,这样我才能在调试模式下更轻松地执行。 【参考方案1】:我最近不得不这样做,当我无法轻松找到任何明确的示例时,我对它的简单程度感到惊讶。我所做的是将以下内容添加到 AssemblyInfo.cs:
#if DEBUG
[assembly: XmlnsDefinition( "debug-mode", "Namespace" )]
#endif
然后,使用 markup-compatability 命名空间的 AlternateContent 标签根据该命名空间定义的存在来选择您的内容:
<Window x:Class="Namespace.Class"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="debug-mode"
Width="400" Height="400">
...
<mc:AlternateContent>
<mc:Choice Requires="d">
<Style TargetType="x:Type ToolTip">
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="FlowDirection" Value="LeftToRight"/>
</Style>
</mc:Choice>
<mc:Fallback>
<Style TargetType="x:Type ToolTip">
<Setter Property="FontFamily" Value="Tahoma"/>
<Setter Property="FlowDirection" Value="RightToLeft"/>
</Style>
</mc:Fallback>
</mc:AlternateContent>
...
</Window>
现在,当定义 DEBUG 时,“debug-mode”也将被定义,并且“d”命名空间将出现。这使得 AlternateContent 标记选择第一个代码块。如果未定义 DEBUG,则将使用 Fallback 代码块。
此示例代码未经测试,但它与我在当前项目中用于有条件地显示一些调试按钮的基本相同。
我确实看到了一篇博客文章,其中包含一些依赖于“Ignorable”标签的示例代码,但这种方法似乎不太清晰且易于使用。
【讨论】:
VS 错误窗格不喜欢这样,尽管一切都按预期工作:link 将代码添加到 AssemblyInfo.cs 时,我的解决方案无法编译。我得到The type or namespace name 'XmlnsDefinitionAttribute' could not be found (are you missing a using directive or an assembly reference?)
。我能做什么?
XmlnsDefinitionAttribute
在 System.Windows.Markup
命名空间中。此命名空间位于System.Xaml.dll
程序集中,我相信它是在您在 Visual Studio 中创建 WPF 项目时自动添加的。
请注意,您可能需要将“mc”标记为可忽略自身,即 mc:Ignorable="d mc"
知道为什么在 Xamarin 中我收到此错误Type mc:Choice not found in xmlns http://schemas.openxmlformats.org/markup-compatibility/2006
?【参考方案2】:
这在 WPF/Silverlight/WP7 中是不可能的。
有趣的是,标准文档ISO/IEC 29500(Office Open XML 文件格式)介绍了如何在 XML 文档中处理这些内容,并且 XAML 确实支持以下项目之一该规范mc:Ignorable
允许我们做这样的事情:
<Page xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:c="Comments"
mc:Ignorable="c">
<Button Content="Some Text"
c:Content="Some other text" />
</Page>
注释掉属性。
XAML 解析器团队(SL4、WP7.1、WPF)选择使用该规范来解决他们忽略属性的需求,而不仅仅是编造一些东西。这就是为什么某些默认 XAML 页面定义了“mc”命名空间的原因。我确实认为,如果 XAML 有朝一日支持允许加载替代内容的其余规范,那会很酷。
Blend 使用mc:Ignorable
属性来支持设计时功能。
【讨论】:
【参考方案3】:您可以使用模板选择器。 DataTemplateSelector 类是您编写的代码。使用您覆盖的模板选择方法,您可以放置您的预处理器指令。
http://msdn.microsoft.com/en-us/library/system.windows.controls.datatemplateselector.aspx
【讨论】:
如果问题是关于备用查看内容,则DataTemplateSelector
可能是相关的,但它是关于备用样式 - 没有“选择器" 用于替代样式。好吧,您可以创建两个单独的内容副本,使用不同的样式……但这听起来不像您在这里要说的。【参考方案4】:
我对其中任何一个都不满意,于是做了这个:
在我的 XAML 中,我将任何属性或标签都放在一个空格中,这样我就知道我在 .cs 文件中搞砸了。
<Window x:Class="...
mc:Ignorable="d"
Title=""
BorderThickness="2"
WindowStartupLocation="CenterScreen"
ResizeMode="NoResize"
Height="200"
Width="500"
WindowStyle="None"
>
然后在我后面的代码中我这样做:
public partial class ScanProgressWindow : Window
public ScanProgressWindow()
InitializeComponent();
#if DEBUG
this.WindowStyle = WindowStyle.SingleBorderWindow;
#endif
为我工作。
【讨论】:
【参考方案5】:我觉得给定的答案并不是最容易使用的。这是我使用自定义可附加依赖属性的解决方案:
using namespace Utility
public static class DebugVisibility
public static readonly DependencyProperty IsVisibleProperty = DependencyProperty.RegisterAttached(
"Debug", typeof(bool?), typeof(DebugVisibility), new PropertyMetadata(default(bool?), IsVisibleChangedCallback));
private static void IsVisibleChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
var fe = d as FrameworkElement;
if (fe == null)
return;
#if DEBUG
fe.Visibility = Visibility.Visible;
#else
fe.Visibility = Visibility.Collapsed;
#endif
public static void SetIsVisible(DependencyObject element, bool? value)
element.SetValue(IsVisibleProperty, value);
public static bool? GetIsVisible(DependencyObject element)
return (bool?)element.GetValue(IsVisibleProperty);
xaml 会像这样使用:
<window ... xmlns:Util="clr-namespace:MyNamespace.Utility" >
<Label Util:DebugVisibility.IsVisible="True">
</window>
我将其保留为布尔值,以防您想在其中添加一些其他可见性逻辑。这是一个不错的简单切换,可以绑定和附加到任何控件
【讨论】:
好主意,但实现可以简单得多。 Debug/Release 显然在运行过程中不会改变,所以你不需要所有的 Binding/Dependency 东西。你所需要的只是 Util 中的一个静态变量“Debug”,即 Debug 时为 True,否则为 False。 (为方便起见,第二个静态“Release”在调试时为 False。)然后执行<Label IsVisible=Static Util:Debug
。
注意:此答案与“条件编译”不同; IsVisible=False
表示创建了视图对象(尽管没有布局调用)。这有一些成本,尽管通常是很小的成本——所以对于某些目的来说是可以的。 对于这个特定问题没有用,这是关于替代 styles - IsVisible 在那里没有帮助。
顺便说一句,如果您的代码基于您在其他地方看到的示例,您应该提供一个链接来感谢其代码帮助您创建此代码的作者。正如here 所提到的,看起来很复杂,因此 VS 设计师可以看到这种变化;如果这就是复杂性的原因,那么您应该提到这一点。以上是关于XAML 是不是有用于调试模式的条件编译器指令?的主要内容,如果未能解决你的问题,请参考以下文章