Need advice on how to change colors - wpf

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

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.

Follow this guide: http://weblogs.asp.net/psheriff/archive/2009/12/01/load-resource-dictionaries-at-runtime-in-wpf.aspx
Create various xaml resource files, but make sure the file does not compile and copies into the bin directory instead.
Decorate your xaml controls with DynamicResources.
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. :)

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.

Related

Apply different styles depending on user theme

I have a WPF application in which I change the default styles a bit, to add some common padding or margin, or something like that. I usually do that either in the Window.Resources or in some resource dictionary I either load in the window’s or application’s resources. An example style could be this:
<Style TargetType="{x:Type Button}">
<Setter Property="Margin" Value="5" />
</Style>
So far so good. Note though that I am changing a default component, not a user component.
Today I noticed that the Aero2 theme that is used in Windows 8 comes with a few different standard styles than I am used to from Windows 7’s Aero theme. Unfortunately I was not really able to make a generic style that would just work in both.
So, I want to be able to specify different styles, depending on which theme the user is using. For example, if the user is using Aero, I want to load Aero-styles.xaml, and if it’s Aero2 on Windows 8, I want to load Aero2-styles.xaml instead.
I was hoping this would be possible by using the Themes directory and providing Aero.NormalColor.xaml and Aero2.NormalColor.xaml. Unfortunately that seems to only work for custom controls, but not the built-in controls. It also does not make the available keys available to be used as a static/dynamic reference.
Is there a way to do this? To provide maybe a base resource dictionary that contains customizations and then another theme-dependent dictionary with minor adjustments to the used theme?
Detect theme on startup (before any UI is loaded), and dynamically add appropriate ResourceDictionary to Application.Resources.MergedDictionaries.
This worked for me.

Design-time data for ControlTemplate

Providing design-time data for DataContext is easy with use of d:DataContext but what about control properties referenced with {TemplateBinding} or {RelativeSource TemplatedParent} from Style.Template ?
Should I just populate control with sample data inside constructor/Loaded event when DesignerProperties.GetIsInDesignMode(this) returns true ?
(Can't do this since it would break normal design experience).
What about third party-controls that I can't modify ?
For my own controls I usually do something like:
<Style x:Key="FooStyle>
<Setter Property="Template>
<Setter.Value>
<ControlTemplate TargetType="FooControl">
<Grid d:DataContext="{d:DesignInstance FooDesignTimeData, IsDesignTimeCreatable=True}">
... guts of control template go here ...
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Where "FooDesignTimeData" is a class that provides design time data in the appropriate form (implementing the interface from your runtime view model is a good practice here).
I don't see why this wouldn't work for a 3rd party control as well. You might not even have to retemplate the control -- you might be able to get away by just specifying the 3rd party control inside of your style and giving it a design time data context as specified above, but I haven't tried that scenario. I assume you're going to all this trouble because you're forced to use a control that does not have a great design time experience (such as by providing a Vendor.Controls.Design.dll or Vendor.Controls.Expression.Design.dll file).
To work with the TemplateBindings, I don't have a great solution. Usually I create a test page that displays my control and allows me to switch templates around. During integration you'll have an extra view (either within your app or as a separate app) that allows you to create and manipulate instances of the control as necessary. The GoToStateAction targeted trigger action from the Blend SDK is often useful here. For example, create a button for each visual state and then use the Click even to trigger a transition to a particular state. Thus you can easily test all of your states plus transitions while bound to test data. Hacky and not really design time data, but it works.

WPF - Which one is better? Style or User Control?

I wanted to know which one amongst Style and UserControl would be better to use in WPF?
For example:
I have created an image button in two different ways.
One uses Style and ContentTemplate property is set.
It uses one other class with dependency properties.
The other way is I have created a UserControl which has a button and its content property is set.
The file UserControl.xaml.cs also contains the dependency properties.
For Code details see the answers of this question:
Custom button template in WPF
Which one would be better to use? In which scenario should one go for Style or UserControl or any CustomControl?
Styles are limited to setting default properties on XAML elements. For example, when I set the BorderBrush , I can specify the brush but not the width of the border. For complete freedom of a control’s appearance, use templates. To do this, create a style and specify the Template property.
Styles and templates still only allow you to change the appearance of a control. To add behavior and other features, you’ll need to create a custom control.
For example,
To create a button like a play button use styles and templates, but to create a a play button which will change its appearance after pausing it use UserControl.
For this type of thing I would go with Style, even though I'm not really adept with graphical tools. I tend to produce a basic, boring style that I can get started with and then prettify it once the application functionality has been verified.
The nicest thing about WPF is being able to distance much of the graphical look, feel and behaviour away from the code.
This allows you to change the style of your application without revisiting the code and indeed means that you can change styles on the fly at runtime.
There is an awkward line to tread with regards to how much behaviour is placed within the XAML and how much is placed within the code. A rough guide would be to decide on what behaviour must always be present within the UI and place that in the code, everything else place within the XAML.
Think of the code as being an abstract class with defined interfaces and the XAML Styles as being classes based on that class and you'll get an idea of what I mean.
Conversely, I know that people who are far more adept at the GUI work prefer to put more functionality in the XAML and others who prefer the code side, because they find the GUI work slow or difficult.
When thought of that way you'll see that there's never really a right or wrong answer, just better solutions that suit your skills.

Setting the colour scheme for a Silverlight app from an external resource

I have a Silverlight 3 application containing six custom user controls. I'd like to load the colour scheme for these controls from an external resource.
The code and XAML containing a default colour scheme would be built in the XAP. Then a parameter on the object tag would contain a URL from where alternate colours can be dynamically loaded.
By the way, the Silverlight 3 application theme feature could be used if that's possible but is really overkill. Only colours need to be changed.
Is this possible and how would you recommend to do it?
Here is how I would do it.
In App.xaml I would define the application Resource dictionary like this:-
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ColorTable.xaml" />
</ReourceDictionary>
<!-- rest of your application resource entries here -->
</ResourceDictionary>
</Application.Resources>
Now I would place the ColorTable.xaml outside of the XAP in the same folder that the XAP is sited. This doesn't quite meet all your criteria since an external ColorTable is always required. It is possible to flex this somewhat to achieve the full requirement but it'll be quite messy in comparison.
I would take a look at the technique Corinna Barber uses in these two articles:
http://blogs.msdn.com/corrinab/archive/2009/11/24/9927729.aspx
http://blogs.msdn.com/corrinab/archive/2009/12/02/9931283.aspx
Basically what she does is, at application startup, she creates a bunch of brushes (both solid and gradients) in a binding helper class (hers is called SysColors). Then she simply binds to these brushes, like so: Background="{Binding CalendarGradient, Source={StaticResource SysColors}}"
The main downside to her approach is that you have to write quite a bit of code when creating gradient brushes. And all the different gradient stops would have to be stored independently in your database (or xml or whatever). I'm thinking now that you could probably store your brushes as xaml and just use XamlReader.Load to load the entire brush object at once. That sounds like a better plan to me, but I haven't tried this, I'm just thinking out loud.
In your situation, at application startup, you could easily load your default scheme OR pick up your color values from a WCF service or wherever. You could even implement INotiyPropertyChanged for all the brushes, and thus be able to swap them at runtime. But I guess that might give you bad performance.

Is it possible to apply Blend behavior using style or template?

I'm very happy with my small collection of Blend behaviors, actions and triggers - they are easy to use and powerful. But I still can't figure out how to avoid applying them on per element basis. For example, if I have a behavior as such:
<Rectangle>
<i:Interaction.Behaviors>
<il:MouseDragElementBehavior/>
</i:Interaction.Behaviors>
</Rectangle>
and I have a few draggable rectangles in my Window, each of them has to have the above markup to be draggable. What I would like to do is to be able to write something like this:
<Style x:Key="RectangleStyle" TargetType="{x:Type Rectangle}">
<Setter Property="i:Interaction.Behaviors"
Value="il:MouseDragElementBehavior"/>
</Style>
It could be style, template, or some other way to avoid behavior or action markup repetition. The best solution I came up so far is creating a special behavior for the container (when attached, it enumerates children attaching to the children events).
Any ideas?
I ran into the same problem and I posted on my blog on how to create an attached property to work around this shortcoming of the Blend SDK.
I haven't tried it, but what I would probably do is create an attached property that can hold a collection of Behaviors. In the property changed handler of that property, I would enumerate the collection and add each of the behaviours to the real Interation.Behaviors property. It's a bit messy, but it ought to work.
Update
This approach won't work without a good deal more work: the problem is that Behaviors and Triggers can only be attached to one object at a time. This is probably why the limitation on applying them using a style exists in the first place. To get this to work you would need to create some kind of Trigger or Behavior factory.
You could create your own class that inherits from Rectangle and apply the behavior there.

Resources