0

I'm building a WPF application that will be run on laptop computers mounted in police cars. The app has to have a "Night Mode" which will use darker colors to be less of a strain on the eyes at night.

Since the application is going to be used while the officer is driving, I've increased the size of all of the controls and I've defined new default templates for things like comboboxes. This is to make the screen easier to read at a glance and to make it easier to hit controls on the touch screen when you have sausage fingers, like I do.

I've created an enumeration called TimesOfDay. There are two values in the enumeration, DayTime and NightTime. Each control has a DepenencyProperty called TimeOfDay of the TimesOfDay enumeration type. There's a button on the main screen that you push to change the value of the TimeOfDay property. When you click the button, it cycles the TimeOfDay property's value between the two values.

I'm still pretty new to WPF, so I'm not sure how to go about this, on the Xaml side. I think what I need to do is create two named styles, for example one called DayStyle and another called NightStyle. Then I need to add triggers somewhere to change the style applied to the controls when the TimeOfDay property changes. Is that right?

Do I just change the background and foreground colors of the controls by type? Can I do it by element name?

I'm very fuzzy on all of this. Any help would be appreciated.

Tony

Tony Vitabile
  • 8,298
  • 15
  • 67
  • 123

3 Answers3

1

Each control has a DepenencyProperty called TimeOfDay of the TimesDay enumeration type.

Don't do that, just create two complete themes in separate ResourceDictionaries which you then can switch via the MergedDictionaries in the Application.Resources. There is no need to put the day-time information on the controls.

Community
  • 1
  • 1
H.B.
  • 166,899
  • 29
  • 327
  • 400
  • This looks interesting and should be easy to do. It works with the way I'm currently setting the colors (I have defined a number of `Brushes` in my app.xaml file that I'm referencing using `DynamicResource` clauses, as in the example). My problem with it is I don't want the `ResourceDictionaries` to be in files on disk. Can I embed them as resources in the executable and retrieve them from there? – Tony Vitabile Mar 22 '12 at 15:48
  • @TonyVitabile: Probably, have not tried it myself yet though, [this question](http://stackoverflow.com/questions/709087/load-a-resourcedictionary-from-an-assembly) might be helpful, meybe there are others as well. – H.B. Mar 22 '12 at 16:18
  • I've only changed a couple of the colors, but I've got the mechanism working. And the ResourceDictionaries are embedded as resources in the executable. Now I just have to set all of the colors for night time and tweak any properites that I forgot to use one of my brush resources in. Thanks! – Tony Vitabile Mar 22 '12 at 18:42
  • This is working great on my main window, but there's a problem. I've got a special Dialog class on which I've implemented all of this stuff, but it won't switch colors. The template for the Dialog class is using the same `DynamicResources` as my main window. Why is the dialog still displaying the daytime colors, when the main window is in night mode? – Tony Vitabile Mar 23 '12 at 21:24
  • Never mind, I figured it out. I had to bind the TimeOfDay property in the dialog to the TimeOfDay property in the main window and then everything works. – Tony Vitabile Mar 23 '12 at 21:32
  • @TonyVitabile: If you had done what i suggested there would not be any TimeOfDay property any more o.O – H.B. Mar 23 '12 at 22:21
0

Follow this guide: http://weblogs.asp.net/psheriff/archive/2009/12/01/load-resource-dictionaries-at-runtime-in-wpf.aspx

  1. Create various xaml resource files, but make sure the file does not compile and copies into the bin directory instead.
  2. Decorate your xaml controls with DynamicResources.
  3. Load in your resources through code.

Basically, you are looking to "skin" your application. The code that loads in your resource file can take advantage of the TimeOfDay enumeration.

If you want it automated you can even have some static class that has a timer to automatically attempt to change the resource and set the timer on the application startup. :)

myermian
  • 31,823
  • 24
  • 123
  • 215
0

I wouldn't duplicate the style, because I hate duplicated code... You could easily achieve that with a trigger in the ControlTemplate:

<Trigger Property="TimeOfDay" Value="NightTime">
    <Setter TargetName="someControl" Property="Background" Value="Black" />
    <Setter TargetName="someOtherControl" Property="ForeGround" Value="Yellow" />
    ...
</Trigger>

Another option is to use the technique I described here. This way you don't even need to put the TimeOfDay information on the control itself, it can be an ambient property.

Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
  • The attached property approach in your blog post looks interesting. I might give that a shot. – Tony Vitabile Mar 22 '12 at 01:53
  • I have to disagree here, as much as I hate duplicated code, in his case it would be a lot easier to maintain 2 styles and trigger them on the app's level than having triggers in each control... he probably does not have many colors in his app anyway, so doing what you do would actually mean more duplicated code than triggering a few colors on the app's level – David Mar 22 '12 at 09:06
  • I've begun trying to use Thomas' suggestion of applying the triggers to the control template. But what I'm not clear on is where do I put them? Most of my controls are UserControls, not custom controls. I do have a few of those, and I suppose I could convert everything over, but do I have to? – Tony Vitabile Mar 22 '12 at 13:13
  • @TonyVitabile, with UserControls triggers won't be very convenient to use. Try using my solution based on attached properties instead – Thomas Levesque Mar 22 '12 at 13:24
  • @ThomasLevesque, The compiler won't let me use {TemplateBinding} in the UserControl Xaml. How do I bind the value of the Background property on a TextBox to a property in my ThemeProperties class, for example? – Tony Vitabile Mar 22 '12 at 15:28
  • @TonyVitabile, if you made the property ambient with the Inherits flag, you can use a normal Binding with `RelativeSource={x:Static RelativeSource.Self}` – Thomas Levesque Mar 22 '12 at 19:00