我该如何让WPF在调试模式下使用一种窗口样式,在发布模式下使用另一种窗口样式?

10

我有两种不同的窗口样式:

  1. 普通 - 窗口有标题栏且可以移动/调整大小
  2. 固定 - 窗口没有标题栏,固定在屏幕中央

这个窗口对于我的开发机上的任一监视器都太宽了,但它恰好适合目标/安装机。因此,在调试时,我需要能够移动窗口以便能看到其上的所有内容,但在发布应用程序时,我需要它以“全屏”模式运行(就像投影仪模式下的PowerPoint应用程序)。

是否有办法根据我是在Debug还是Release模式下编译来设置窗口的Style属性?我想可能可以使用绑定,但我不太确定如何实现它。

6个回答

16
创建一个样式选择器类:
namespace WpfApplication1
{
    public class DebugReleaseStylePicker
    {
        #if DEBUG
                internal static readonly bool debug = true;
        #else
        internal static readonly bool debug=false;
        #endif

        public Style ReleaseStyle
        {
            get; set;
        }

        public Style DebugStyle
        {
            get; set;
        }


        public Style CurrentStyle
        {
            get
            {
                return debug ? DebugStyle : ReleaseStyle;
            }
        }
    }
}

在你的App.xaml中, 在Application.Resources中添加你的调试和发布样式+一个StylePicker实例,并设置ReleaseStyle和DebugStyle为之前设置的样式:

<Application.Resources>
        <Style x:Key="WindowDebugStyle">
            <Setter Property="Window.Background" Value="Red"></Setter>
        </Style>

        <Style x:Key="WindowReleaseStyle">
            <Setter Property="Window.Background" Value="Blue"></Setter>
        </Style>

        <WpfApplication1:DebugReleaseStylePicker x:Key="stylePicker"
            ReleaseStyle="{StaticResource WindowReleaseStyle}"
            DebugStyle="{StaticResource WindowDebugStyle}"/>
    </Application.Resources>
在您的窗口标记中将WindowStyle设置为以下内容:
<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300"
        Style="{Binding Source={StaticResource stylePicker}, Path=CurrentStyle}">  
..
</Window>
您可以重复使用DebugReleaseStylePicker来将样式设置为任何其他控件,而不仅仅是Window。

我非常喜欢这个解决方案的灵活性。我可以看到在其他领域也使用类似的技术。谢谢! - devuxer

5

在XAML中可能很难做到,但在实际代码中,你可以像这样做:

#if DEBUG
    window.Style = WindowStyles.Regular;
#endif

为什么不把它放在正常的XAML代码执行后执行的某个位置呢?

我按照这个方法做了,它是可行的一种方法。我发现代码中的 WindowStyle = WindowStyle.SingleBorderWindow 对我不起作用。 - Firedragon

4
你可以创建这样的标记扩展:

你可以创建一个标记扩展,就像这个例子:

public class DebugStyleExtension : MarkupExtension
{
    public object DebugResourceKey { get; set; }
    public object ReleaseResourceKey { get; set; }

    public object ProvideValue(IServiceProvider provider)
    {
#if DEBUG
        return Application.Current.FindResource(DebugResourceKey) as Style;
#else
        return Application.Current.FindResource(ReleaseResourceKey) as Style
#endif
    }
}

你可以这样使用它:
<Window ...
        xmlns:my="clr-namespace:MyNamespace"
        Style="{my:DebugStyle DebugResourceKey=DebugStyle, ReleaseResourceKey=NormalStyle}">

我喜欢这个,但它无法编译:需要对象引用才能访问非静态字段、方法或属性“System.Windows.Application.FindResource(object)”。有问题的代码是 Application.FindResource。这个类文件需要与我的应用程序在同一个程序集中吗?谢谢。 - devuxer
谢谢你修复了那个问题。我还注意到另一个问题,虽然我不认为它与你的代码有任何关系。在#else后面紧接着的那行代码显示为灰色文本,并且没有响应智能感知。你有什么想法是什么原因吗?再次感谢。 - devuxer
这是因为您正在调试模式下。编辑器知道此代码不会被编译(因为已定义DEBUG符号),因此它将其显示为“禁用的代码”。 - Thomas Levesque
哦 :) 这很有道理,只是我不明白为什么智能感知不起作用。 - devuxer
我猜编辑器会将它处理为“非代码”部分,就像注释一样... 如果你想编辑这部分内容,请切换到发布模式 ;) - Thomas Levesque
显示剩余2条评论

2

您可以在XAML文件以及代码后台中进行条件编译。 查看这篇文章

基本上,在您的Properties\AssemblyInfo.cs文件中,您可以这样做:

#if BETA
[assembly:XmlnsDefinition("BetaVersion", "Example.Technology")]
#endif

将xmlns添加到*.XAML文件中:

xmlns:beta="BetaVersion"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

现在,您可以这样做:
<mc:Choice Requires="beta">
  <Label>
    This is ALPHA software. Confidential.
    Internal use only. Do not distribute
  <Label>
</mc:Choice>

作为附注,这可能不适用于Silverlight - 据我所知,assembly:XmlnsDefinition 不受支持。

作为一个旁注,XmlnsDefinition在Silverlight 4版本中已经被添加。 - Muad'Dib
文章不幸已经损坏。 - Firedragon
有许多替代教程可以取代链接文章。只需使用您喜欢的互联网搜索来查找“http://schemas.openxmlformats.org/markup-compatibility/2006”和“条件编译”。 - Peter Duniho

0

你能否使用#if DEBUG将属性设置为不同的值并绑定它?

也许可以。

#if DEBUG
style = 0;
#else
style = 1;
#endif

(请记住我这里没有VS。)并使用一个值转换器。

被Skeet先生打败了,他的枪还更好!该死! - serialhobbyist

0

有很多有用的答案...我想到了另一个想法,我想提出来:一个值转换器加上一个绑定:

这是值转换器:

    public class WindowToWindowStyle : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var window = (Window)value;
            var style = (Style)window.FindResource("Window_FixedStyle");
#if DEBUG
            style = (Style)window.FindResource("Window_Style");
#endif
            return style;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return Binding.DoNothing;
        }
    }

这是我的窗口声明:

<Window
    ...
    xmlns:local="clr-namespace:MyProj"
    Style="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource ValueConverter_WindowToWindowStyle}}"
    WindowStartupLocation="CenterScreen">
    <Window.Resources>
        <local:WindowToWindowStyle
            x:Key="ValueConverter_WindowToWindowStyle" />
    </Window.Resources>
    ...
</Window>

这段代码的作用:

这里发生的事情是,我将窗口本身的引用传递给值转换器,它返回相应的样式。


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