I need certain elements to change look (change color, add text, etc...) when user holds SHIFT key to show it will affect that item.
Not all items will have same DataContext so I believe I can not just bind it to one DependencyProperty in MainWindow.
Each will have something like
<DataTrigger Binding="{[ShiftPressed]"} Value="True">
<Setter [change color/add text/...]/>
</DataTrigger>
How would you do it? Would that affect performance much if a lot of ListBoxItems listened it?
I would be tempted to use the data trigger to bind to a Boolean property called something like "IsShiftPressed", and use the the visual state manager, along with the DataStateBehaviour to toggle between two states for each of your controls: a normal state, and a shifted state.
Your various controls would then be listening to a single bool property change, rather than implementing multiple key triggers. You'd have more control over when and how that state is triggered.
If you were concerned about performance, I'm not sure how WPF handles things like this under long list scenarios, but providing your lists are virtualised in the list boxes, there shouldn't be any major performance hits to worry about using the state manager.
UPDATE: just realised that you already have the Boolean property defined in your question. Sorry about that!
Related
Are the names for states and VisualStateGroups in VisualStateManager arbitrary, or do they have deeper meaning?
They seem similar to pseudo-classes in CSS, in some ways (Button has CommonStates: Normal, PointerOver, Pressed, and Disabled, whereas CSS has :hover, :active, and ways of targeting disabled controls). But they are also different—Checkbox has (it seems) completely different states, like Checked, Unchecked, and Indeterminate.
As I develop my apps, how do I know which VisualStates are available? What happens if I use the wrong names?
Disclaimer: I work for Microsoft.
Do the names for states hold deeper meaning?
Are the names for states and VisualStateGroups in VisualStateManager arbitrary, or do they have deeper meaning?
The names for states and VisualStateGroups are indeed arbitrary, but they do have a deeper meaning.
VisualStates in VisualStateManager are [representations of] the visual appearance of a UI element when it is in a specific state. They use Storyboards or Setters to represent arbitrary changes to a given Control (for example, make the background red). Control authors can call VisualStateManager.GoToState within their codebehind to activate a named VisualState.
In this way, VisualState names are arbitrary: I could create a VisualState named CitelaosGreatState and activate it by calling GoToState(this, "CitelaosGreatState"). That's why there's such a variety of names—Buttons have the CommonStates you mentioned, while Checkboxes have completely different ones.
However, for practical purposes, the VisualState names you choose are not arbitrary.
If you are using a VisualStateManager to modify the look & feel of a default control (by overriding the ControlTemplate), you almost certainly want to pick VisualState and VisualStateGroup names that correspond exactly to the names in the original ControlTemplate (which you can find in the XAML designer or in generic.xaml). This is a matter of functionality: the implementers of, say, Button chose an arbitrary name for the VisualState that appears when you hover a Button—CommonStates PointerOver. The logic in their codebehind that handles hovering a Button calls GoToState(this, "PointerOver") (or some equivalent). If you want to customize that appearance, you have to provide a VisualState with that name.
You can certainly also provide a cool state named CitelaosGreatState, or even Hover, but if the codebehind never calls GoToState with that same string, your state will never be activated, no matter the name.
Of course, that means for completely custom controls (where you control both the VisualStateManager and calls to VisualStateManager.GoToState), you can name your states whatever you want!
How do I know which names to choose?
As I develop my apps, how do I know which VisualStates are available?
Completely custom controls: as above, if you are writing both the VisualStateManager and the calls to VisualStateManager.GoToState, name the VisualStates whatever you want! If you define a state named State1, you can activate it in codebehind with GoToState State1.
Custom templates for existing controls: if you are retemplating an existing control (using ControlTemplate), you should choose names that match the existing states on that control. For example, Button defines CommonStates: Hovered, PointerOver, Pressed, and Disabled. Define those. States with other names will not ever be activated (since the codebehind written by the XAML team doesn't ever GoToState with that name). To know the existing states—
How do I know the existing VisualStates of a control?
Look up the default ControlTemplate (or Style with TargetType of your desired type) for your control (which, as mentioned earlier, you can find in the XAML designer or in generic.xaml).
Use the names in the template's VisualStateGroup.
Wrong name?
What happens if I use the wrong names?
Since the names are arbitrary, "wrong name" is not the clearest question here. It's easier to look at two cases:
You define a VisualState that codebehind never activates with GoToState (e.g. you added a state called CitelaosGreatState or Hover to your custom template for a Button): nothing awful happens, but your state will never be activated.
You fail to define a VisualState that codebehind tries to activate (e.g. you added an incomplete VisualStateGroup for your custom Button template): the GoToState call has no effect.
Is it possible to change the "default" forecolor of a label?
I know I can change each control one-by-one in either design time or run time but I wonder if there is a better way.
I can do this at run time
lblCompanyName.ForeColor = color.darkblue
I could also have a loop to look at all of my controls on the form and change them in one small bit of code, but there must still be a better way.
I see at design time that the "default" label forecolor is "ControlText" so can I change ControlText perhaps to equal color.darkblue and then all of my labels will be dark blue without needing to code it one control at a time (or within a loop).
Thankyou
David.
You can't change it for a standard Label control but you can always create your own class that inherits Label and then sets the ForeColor property in the constructor. You would then use that control instead of a Label.
EDIT:
If you want to change the text colour for all your Label controls at run time then you should use a bound application setting. On the Settings page of the project properties, add a setting of type Color with User scope and name it LabelForeColor or something else if you prefer. Now, select a Label in the designer, open the Properties window and use the (ApplicationSettings) -> (PropertyBindings) node to bind the ForeColor property to the setting you created.
You can then access that setting in code via My.Settings.LabelForeColor and any Label bound to it will be updated automatically. You can bind as many different Label controls on as many different forms as you like. You can only bind one at a time though, so I would recommend copying and pasting an existing bound Label rather than adding a new one each time. If you have existing Label controls and you're confident enough, you can copy, paste and edit the binding code in the designer code file(s).
There's really no point your using a custom control in this case because the setting will control each control anyway. No matter what value you set in the constructor, it will still be set by the bound setting afterwards. Note that any change you make to a setting will be automatically saved at shutdown and reloaded at startup.
I am trying to implement a custom control which will show different content according to 3 different control states. I've achieved this by adding a state, and 3 different content properties to my control.
What I have now is something like that.
User sets CurrentState property to one of, "Default", "CurrentStep" or "Completed".
Control switches to a different visual state via VisualStateManager.
Controls default template sets Visibility property on 3 different ContentPresenters to display single content.
It's all working with no problem. What I am struggling to do is enabling design time support. The only thing I can do is to set ContentProperty attribute to one of the content properties, so that Blend shows this property as a child in it's control tree. However this enables only one content property to be editable in design time.
What more can I do to add design time support to my control?
I would not have created a custom control with multiple contentPresenter.
To achieve what you are trying to do, most of the time, you create a control with named parts (the default winrt control templates use this "named parts" mechanism).
When your custom control state changes, you simply show/hide one or more named parts.
This way your can provide a default control template, with all the named parts you require, and to customize the control, you override the default template, and define your own parts. The show/hide logic depending on the states will remain the same, but the target control choice is up to the guy writing the template.
I use the VisualStateManager-Element to re-locate some XAML-elements on my page based on the current Visual State.
My problem is that I use a gridview which has to become a listview when the window is snapped (because of the small horizontal space left). I bound some other elements to the gridview's selectedItem property. My first approach was to create a listview and show/hide it based on the visual state. I would need to update the binding of my other elements as well though ( from gridView.selectedItem to listView.selectedItem) which is apparently impossible in the visualstatemanager. Another possibility would be to change the binding from code behind.
Are there other solutions (preferably in XAML)?
I think the generally accepted answer would be that you should have a piece of xaml per visual state. You collapse the one that is not currently in use. You would only make changes or create bindings manually if you were going to do something that required a dynamic number of bindings or something similar. In this case you have a fixed set of bindings to a known set of UI elements, so you would simply setup all the bindings in xaml.
I have two controls. The XAML's are big and very similar. One difference is this: they contain a listbox, in one control, it's bound to {StaticResource X}, and is multiselect, the other is bound to {StaticResource Y}, and is not multiselect. The code-behinds are also very similar. How should I combine these two classes into one? I thought about creating a base class and deriving my 2 controls from it, but I have no idea how to do that with XAML. I know I could make it easier if I set the differing properties in code instead of XAML (in which case the XAML's would become identical), but let's consider that plan B. Silverlight has no StyleSelector, it seemed like a possible solution though. Maybe VisualStateManager could do it, except it sounds bad, because my problem has nothing to do with visuals, but maybe I could define 2 states anyway. Except I think SL doesn't support binding in style definitions. Tough question for a beginner like me...
You should look into creating custom controls and using AlternateContent properties. Look these up and you'll find hundreds of tutorials.
Here's a quick google search to get you started with alternate content.
So, to sum it up, I want one control which can work in somewhat different modes, or states. The mode can affect XAML properties and code logic, too.
It seems like VisualStateManager is very limited in which properties it can manipulate. But when the differences are only visual, it's the best choice.
When there are other differences in XAML, then the obvious choice is to omit those properties from XAML and set them in code, like in the ctor. A nicer way is to expose those properties as dependency properties in code, bind to those properties in the XAML of the user control, and then you can specify those properties in other XAML's where you use this user control. When your control doesn't care what's in those properties, then it's a good design choice, too. In my case, though, when setting up those differing properties should be the responsibility of the user control itself, not its parent, and I want to expose a single mode property only, it's not good.
For this case, the best way I found so far is this:
create a normal user control (XAML+code), expose the differing properties (simple, not DP's) and bind to them in XAML
make this user control abstract, and possibly some properties, too
for each different mode the control needs to support, derive a class from this base control (code only, no XAML), provide implementations for the abstract properties
instead of using the base control in other places, use one of the derived implementations
This way, you can easily specify from outside which mode you want your control to work in. The drawback is that it's not easy to change the mode, since it's not a property you need to change but the type and instance of the control.
And finally, when there are code logic differences, too, then one way is exposing a mode property, or using the abstract class method I described above. For example, a button click handler function can be abstract, too.