views:

343

answers:

6

I have two different styles for my window:

  1. Regular - window has title bar and can be moved/resized
  2. Fixed - window has no title bar and is fixed at the center of the screen

The window is too wide for either of the monitors on my development machine, but it's a perfect fit for the target/install machine. So, when debugging, I need to be able to move the Window so I can see everything on it, but when I release the app, I need it to run in "full screen" mode (like a PowerPoint app in projector mode).

Is there any way to set the Style property of the window based on whether I'm compiling in Debug vs. Release mode? I was thinking I might be able to use a binding, but I'm not quite sure how to implement it.

+4  A: 

It may be hard to do it in XAML, but in actual code you could just do something like:

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

Why not put that somewhere that will be executed after the normal XAML code has been executed?

Jon Skeet
A: 

Could you use an #if DEBUG to set a property to a different value and bind to it?

Maybe

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

(Bear in mind I don't have VS here.) and use a valueconverter.

serialhobbyist
Beaten by Mr. Skeet and his was nicer, too! Damn!
serialhobbyist
+2  A: 

You could create a markup extension like this one:

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
    }
}

you would use it like that :

<Window ...
        xmlns:my="clr-namespace:MyNamespace"
        Style="{my:DebugStyle DebugResourceKey=DebugStyle, ReleaseResourceKey=NormalStyle}">
Thomas Levesque
I like this, but it won't compile: `An object reference is required for the non-static field, method, or property 'System.Windows.Application.FindResource(object)'` The offending code is `Application.FindResource`. Does this class file need to be in the same assembly as my App? Thx.
DanM
I just fixed the code (`Application.Current.FindResource` rather that `Application.FindResource`)
Thomas Levesque
It can be in the same assembly or in another one. If it is in a different assembly, you must specify the assembly name in the xmlns declaration
Thomas Levesque
Thanks for fixing that. I'm noticing one other problem, though I don't think it has anything to do with your code. The line of code immediately following the `#else` is showing up in gray text and not responding to intellisense. Any idea what could be causing this? Thanks again.
DanM
That's because you're in debug mode. The editor knows that this code won't be compiled (because the DEBUG symbol is defined), so it shows it as "disabled code".
Thomas Levesque
Ohh :) That makes a lot of sense, except I don't get why intellisense wouldn't work.
DanM
I guess the editor handles it as a "not code" section, like comments... if you want to edit this part, switch to release mode ;)
Thomas Levesque
A: 

you can do conditional compilation in the XAML file as well as the codebehind. check out this article

basically, you do like this in your Properties\AssemblyInfo.cs:

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

add your xmlns to the *.XAML file:

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

now, you can do like this:

<mc:Choice Requires="beta">
  <Label>
    This is ALPHA software. Confidential.
    Internal use only. Do not distribute
  <Label>
</mc:Choice>

as a side note, this probably wont work with silverlight--AFIK the assembly:XmlnsDefinition is not supported

Muad'Dib
+4  A: 

Create a Style picker class:

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;
      }
     }
    }
}

in your App.xaml add to your Application.Resources your debug and release style + a instance of the StylePicker and set the ReleaseStyle and DebugStyle to the previous set up styles:

<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>

In your Window markup set up the WindowStyle like this:

<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>

You can reuse the DebugReleaseStylePicker to set the style to any other control not just the Window.

Claudiu
I really like the flexibility of this solution. I could see using a similar technique in other areas too. Thank you!
DanM
A: 

Lots of helpful answers...I thought of another idea I thought I'd throw out there: a value converter plus a binding:

Here's the value converter:

    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;
        }
    }

Here's my Window declaration:

<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>

What this does:

So, what's going on here is that I pass a reference to the Window itself into the value converter, and it returns the appropriate style.

DanM