I have a very large ControlTemplate (200+ lines) with many nested controls inside. I need to reuse this template with a small change to one of these nested controls (visibility of a checkbox). Obviously I don't want to copy-paste into a new ControlTemplate and just make that change because I'll double the code base and if I make a common change to the template I'll need to change both.
I've thought of three solutions that seem like they may work, but I don't know enough about XAML (and especially refactoring XAML to know if these are possible)
Extract the common XAML into a base ControlTemplate and 'override' the checkbox visibility in two new ControlTemplates (I place the override in quotations because I'm using C# speak - I've no idea if that makes sense in XAML!)
Gain access to the checkbox (via x:Name or x:Key maybe) from outside of the ControlTemplate definition, then setting the Visibility would be trivial.
Specify some kind of binding on the Visibilty in the ControlTemplate, something like:
<Checkbox Visibility={Binding someNewPropertyOfTheTemplate}/>
(Is this what TemplateBinding is used for?)
Are any of these ideas valid? And if so, which is the most appropriate? (If not - what is the correct way?)
I'm using VS2010 with .Net 4.0.
I would go for #3. But your code is not quite correct. If you want to bind to properties of the actual control, on which template is being applied, you should use TemplateBinding. Suppose you have a custom control with a property ShowCheckboxes. Then in your template you should use
<Checkbox Visibility={TemplateBinding ShowCheckboxes,
Converter={StaticResource BooleanToVisibilityConverter}}/>
Note, you may have to reference or create appropriate converter.
On the other side, if you use MVVM, you may define your control property on the viewmodel class. Then you should use {Binding}.
Also, there is another way to control which templates are applied.
You may extract the template for your subcontrol out of the big template. And copy it, so you have two templates, that differ in the way you need.
Then, in the main template you can set TemplateSelector for your subcontrol to the custom class, that you will implement. Look at the http://msdn.microsoft.com/en-us/library/system.windows.controls.datatemplateselector.aspx for more examples.
Related
I inherited a project that uses a RadioButtonList which inherits from a ListBox. It was taken off the web (currently cannot find a link to), and contains RadioButtonList.cs (which contains six dependency properties) and RadioButtonList.xaml (which is just styles and control templates).
This control is used in over a hundred places. It causes problems because it is not a complete and professional control. Problems such as, focus issues, keyboard navigation, and so on. (See comments.)
After much research at different times over the last couple years, it seems that this control is really not necessary. All that is needed is to set the GroupName property on a group of radio-buttons. And, the only reason why a RadioButtonList control is used is to help with data-binding a list of options through the inherited ListBox.
1) Is this control really necessary? Is there a better way?
2) Is there a professional control, open-source or otherwise, that will allow me to get the benefits of data-binding without the headaches? (We use Infragistics and DevExpress, but I am not familiar with all the controls these suites offer.)
My Answers
1a) Is this control really necessary?
If you only need one list of radio buttons, then no this control is not necessary.
If your applicaton uses many lists of radio buttons, then yes this control is necessary.
If you use a list of radio buttons in different applications, then yes this control is probably necessary.
1b) Is there a better way?
I say that deriving from a ListBox, ItemsControl, or whatever then creating styles and templates is the only way to create this control; therefore, no there is no better way.
2) Is there a professional control...
Definitely, the ListBoxEdit with the RadioListBoxEditStyleSettings.
Comments Regarding Answers
All the answers indicate that creating a RadioButtonList control is not necessary. Yet, if you need more than a couple lists of radio buttons, by the time you create the styles and control templates and maybe data template, you will end up with a collection of code artifacts that can be called a radio-button-list-control. Therefore, in my opinion, a RadioButtonList is necessary.
Moreover, my understanding is a RadioButtonList was dropped in an early WPF CTP. Which I can understand, because of the limited need for such a control that can easily be created.
Comment Regarding Accepted Answer
2) Is there a professional control...
Definitely, the ListBoxEdit with the RadioListBoxEditStyleSettings.
Lastly Comment on Mike Strobel's Answer
The RadioButtonList that I have is the end-result of his answer. While I am good at creating custom-controls, I rather let third-party component makers, such as Infragistics and DevExpress, create and support a basic control like this one.
Is this control really necessary? Is there a better way?
As #lawc points out, no, it is not necessary. It may, however, be preferable, depending on what level of flexibility you desire. A reusable style is easy enough to create, but doing it "correctly" is a bit more involved than simply setting a custom ItemTemplate.
Using Styles
An ItemsControl in WPF will wrap its items in appropriate containers. Each of the selector controls in core WPF overrides the logic which determines whether an item is capable of serving as its own container, as well as the factory code which produces new item containers. A ListBox, for example, will wrap each of its items in a ListBoxItem (unless the item itself is already a ListBoxItem). The style applied to these containers can be set for the parent ItemsControl via the ItemContainerStyle property. This differs from the ItemTemplate property, which allows you to control the appearance of the item within the container. More specifically, it overrides the content template applied to the ContentPresenter within the container.
Since a RadioButton does not derive from ListBoxItem, simply setting the ItemTemplate will produce a list of RadioButton controls embedded within ListBoxItem controls, which means they will still have the same selection chrome normally associated with ListBox controls, and possibly some layout and focus oddities. This is probably not what you want.
Instead, override the ItemContainerStyle and use it to assign a custom ListBoxItem template which embeds a RadioButton. You can probably get away with not setting the GroupName property at all, which eliminates possible name collisions. Instead, just establish a two-way binding between the RadioButton.IsChecked property and the templated parent's ListBoxItem.IsSelected property.
In order to use this technique conveniently, one generally creates a Style resource (available application-wide) which can be applied to the appropriate ListBox instances, and which sets the ItemContainerStyle. Alternatively, you can make the container style available as a global resource and set that on your ListBox instances. Either way, you need to set a property.
Using a Custom Control
While WPF evangelists often recite the philosophy of preferring custom styles over custom controls, in practice this is not always convenient. You may find it more convenient to create a RadioButtonList which extends the ListBox control, and then give it a default style which automatically applies the custom style described above. This gets you out of manually assigning the list style or container style on every ListBox instance, but it's not a huge win.
But maybe you want a bit more control over the appearance of the RadioButton items. For instance, you may want to:
Adjust the margin around the "bullet" of each RadioButton item;
Adjust the vertical alignment of the bullets relative to the content;
Support both horizontal and vertical orientations;
Automatically disable the RadioButton content for items which are not selected.
Creating your own implementation, most likely derived from ListBox, allows you to add these features easily, even after you are already using your radio list across your application. This could be done with the technique above too, though it may require an attached behavior or some attached properties, in which case you end up with a somewhat fragmented design.
Third-Party Solutions
Is there a professional control, open-source or otherwise, that will allow me to get the benefits of data-binding without the headaches?
This is not an uncommon use case, and I have no doubt there are some implementations floating around. Some may be in open source frameworks, and some may be extracted from open source applications. As for third-party implementations, I do know that Actipro ships a RadioButtonList in their Shared WPF library, which is included with all of their WPF components. When last I checked, it was not available on its own. It does, however, support all of the additional features I listed above.
I can only tell you that DevExpress uses a ListBoxEdit with a RadioListBoxEditStyleSettings to represent a group of RadioButtons. Practically it is the same as your control you are using, but i think it provides better functionality and is well tested. A RadioButton is not provided by DevExpress and in my application i use the Default RadionButton-Control provided by WPF/Silverlight.
You use the RadioListBoxEdit of DevExpress as follows:
<dxe:ListBoxEdit SelectedItem={Binding CheckItem, Mode=TwoWay}>
<dxe:ListBoxEdit.StyleSettings>
<dxe:RadioListBoxEditStyleSettings />
</dxe:ListBoxEdit.StyleSettings>
</dxe:ListBoxEdit>
More information about the ListBoxEdit of DevExpress can be found here
In my opinion you don't need this control.
You can simply use .Net ListBox to achieve all your existing functionality.
Using ListBox.ItemsSource you can data bind your options collection
Specify ListBox.ItemTemplate containing the RadioButton, in this template you can data bind your view model property to RadioButton.GroupName
IMHO, a control deriving from ItemsControl would be the cleanest approach.
Then you probably would override
IsItemItsOwnContainerOverride() with return item is RadioButton;
GetContainerForItemOverride() to return a new RadioButton() for each item and
PrepareContainerForItemOverride() to set up binding of ToggleButton.IsCheckedProperty and ContentControl.ContentProperty.
While these parts are just boilerplate code, some more efforts may lie in the implementation of the keyboard behavior.
I have often bemoaned the fact that the WPF ToggleButton does not have properties for AlternateContent and AlternateContentForeground. I'm curious if there's any advantage to creating a DependencyObject with attached properties, or deriving a custom control from ToggleButton?
My assumption is that attached properties are advantageous if they are useable on more than one control. So in my case I'm leaning towards a derived control since those properties are unique to the togglebutton.
AttachedProperties are useful in a couple scenarios:
You want to use them as attached behaviors on things that interact with another Control, like Grid.Row
You want to add properties to a control but you don't want to force clients that get that behavior to be derived from your specific type. E.g. if you had a behavior that you wanted on Buttons rather than ToggleButton, then you may want to go with that approach so you could get that new property on ToggleButton and RadioButton, rather than forcing someone to derive from MyCoolButton.
For what you're describing just subclassing ToggleButton seems to make sense.
Actually, this kind of styling should be done with a trigger, or using the VisualStateManager.
So much reading, and so much about inheritance, I can't find any direct answers, so here goes.
If you have a base-class derived to do certain things, look or act a certain way, you can subclass it and get all the functionality of the parent class with only slightly modified differential. The same does not appear to be the same for working with WPF Themes... more specifically, the combobox control (similar issues with textbox, but that's obviously less complex).
By looking at the Control Template Examples, they discuss the entire structure of it, the borders, backgrounds, glyphs, actions, properties, etc.
If the ONLY thing I want to do with a combobox is to change the border of it to Red if there is an error in it, it appears, I have to basically redefine the entire thing and somehow put in my custom trigger setting / color to be implemented.
Somewhat similar is that of the textbox control and how its created. It has the named control when trying to nuts around with the background color... you can't just say... background = some static brush value.
What shortcuts are out there to only allow overriding these small elements without having to re-create the entire template control. I can just imagine what would go on with grids, tabbed controls, and others that could get extremely messed up if you miss one simple thing.
I also see that some controls are made up of OTHER Control.Templates, so how might I be able to attach to changing the property setting on just the single element of the control template... Such as the combobox has the control template for the Toggle Button. From that, it has a border via x:Name="Border" and I want to change THAT element within a derived style.
Thanks
I might not understand your question here. But from what i get is:
Yes you can't partially implement Templates, in fact i wouldn't know how this could be possible. But, if you want to change certain things, you can of course do that. You can create Styles, Templates, Brushes etc. as DependencyProperties and use TemplateBinding to bind to them, on the given child control.
Remember that WPF allows always to change the template on the fly. if we could partially change the template this would might hurt performance or could get messy and complicated. Still, you can do that using ContentControls and TemplateBinding or simply Triggers.
For my custom controls, which might contain multiple part sub controls, i usually add a style for them. For example, a custom ComboBox would contain a ToggleButtonStyle.
One thing that would be nice though, would be to add control template triggers without the need to reimplement the template.
Folks
I am working in UI design in a project where our team chose to decouple C# and XAML as much as possible.
I've been having trouble to create Styles for many common widgets (buttons, etc.) and some UserControls, specially because I don't-want/don't-know-how/am-not-supposed to use code-behind.
What I want to do is to be able to change properties of elements that are "deep within" the layout tree of my UserControls.
For example, suppose I have an UserControl that is a Border, which contains a StackPanel, which contains a colorful Ellipse and other things.
I want to be able to instantiate this user control and change only the color of the ellipse, like this:
<MyUserControl Background="Gray" EllipseColor="LightGreen" />
where "EllipseColor" would be some "custom" property defined in the UserControl.
I tried DependencyProperty within styles, but got no success, although I "feel" there must be a simple way to do this.
Any help (links, code snippets) would be much welcome.
Thanks for reading.
The "No Code Behind" rule in MVVM is for keeping the View and the ViewModel completely separate, and should not be used for view-specific code such as DependencyProperties. Its like saying "Build a house out of these square blocks, but I want a rounded roof and you can't create your own building blocks". The whole point of DependencyProperties is to create additional Properties for your Views that don't already exist.
The important bit is that the View doesn't directly reference the ViewModel, and vise versa.
In your case, I would either create a DependencyProperty in the Code Behind for your UserControl for EllipseColor, or use something like the Background property of the UserControl and bind my Ellipse fill color to that.
I am new to WPF and I have a doubt in modifying a control. I came to know that one can modify a control by changing its Control Template. i.e.,
<Button>
<Button.Template>
<ControlTemplate>
...
</ControlTemplate>
</Button.Template>
</Button>
Also we can edit a control utilizing the Content Model. i.e.,
<Button>
<Grid>
<CheckBox>
</CheckBox>
<RadioButton>
</RadioButton>
...
</Grid>
</Button>
What is the difference between these two techniques. Which one is the correct way to customize a control in WPF. Please help me in understanding this better.
The primary difference between these two things, is that the ControlTemplate defines the look of the control. It is not actually placing content inside of it. At some location inside the content control, there should be some form of ContentPresenter. The built in controls are capable of this because they are what is known as 'lookless controls', and any custom controls created should also be lookless. When a control is not templated in a lookless manner but instead has a static layout, then the confusion you have run into can occur.
As for the correct way to do things, it depends on what you are trying to achieve. If you are attempting to change the control, such as the look and feel or the behavior, then using a ControlTemplate, (or DataTemplate, depending on what you are templating), is definitely the way to go. A good example of this is the CheckBox, belive it or not, the CheckBox is actually a ToggleButton (more or less), that through templating displays the togleablity in a bullet. Here's another very good example of how you can use Templates to do some very nifty things.
ControlTemplates should also be applied through Styles, instead of directly set on an element.
If you aren't actually aiming to modify the behavior or look of the control then using the content model is the correct approach.
WPF does this better then Silverlight, though I don't know if there are improvements in SL3.
My rule of thumb is that if it's possible to get what I want without changing the control template then you shouldn't change the control template.
control templates are a way to change the look&feel of a control, for example making a round button of changing the check mark graphics of a checkbox.
adding controls inside a control is simpler, for example place an image inside a button.
Also remember, there is a lot of functionality in the control template, including padding, content alignment, disabled look and more, if you change the control template you will have to add support for all of those features.
Template can be placed into a resource and re-used for another button.
Changing content directly is not re-usable unless you make a UserControl out of it.
Which one you use depends on a concrete task and your personal preferences.