I would like to create a user control that you can drag and drop from the tool box to your XAML but that has not interface at all. I was used to do it for timers and background workers and this kind of elements.
So you allow users to drag into their projects and then set the name and other properties through the properties panel, attach functions to events in the event panel and they may perform almost all the set up without writing a single line of code (some customers love that)
Is that even possible ??
There is no "Component" type class like you might have used in WinForms, etc. However, you can probably just derive from FrameworkElement. By default it does no rendering so nothing will show up and as long as you don't set any Margins, MinWidth, etc. it shouldn't affect the layout really either. You might be able to derive from UIElement but using FrameworkElement will mean your object will have access to the DataContext so properties on it can be bound to things on it.
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 need to create a basic user control with certain functionality (like dragging, minimizing and more..).
Now I need a bunch of other user controls to inherit from it and add their content.
I want an option to add new user controls that implements only a part of the base control and remains with the rest of the elements and functionality.
How can I bind a certain element (grid, stackpanael,.. whatever..) from the base user control to the new control? (without loading xaml in the code behind)
I basically want to "plant" a xaml element in a dedicated element on the base user control from a different user control.
If you write a custom control, one of the Controls you can use in the template is called a "ContentControl." Then when you use the Custom Control on a page, you can specify in xaml what the content is going to be. Thus you can put in a Grid, StackPanel, whatever in there.
But note that writing your own Custom Control is rarely done other than by 3rd party component vendors, as it requires a fairly deep knowledge of SL (for example, how to use Dependancy Properties). More commonly used is the "User Control" which is far easier to use and requires no such knowledge. I usually start by trying to accomplish what I need with a UserControl, and if I hit a roadblock, then switch over to a CustomControl.
But most of the existing controls already come with the functionality you describe - drag and drop, minimize etc. SL has a rich UI control set already, so a good place to start is by seeing if one of the existing controls has most of what you need, and then take it from there.
Greg
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.
Assume that I need to create a class called PictureWall, which will be used to show pictures.
Now I find that Panel and ItemsControl can both be used to hold Children elements. So should the class PictureWall derive from Panel? or should it derive from ItemsControl.
Note: This is not a real requirement, it's just a hypothetical question. The real question is: when should I create a subclass of Control (or ItemsControl) and when should I create a subclass of Panel?
Note 2: This imagined picture wall control is not to be used in one application only. It may be used by other developers. If it derives from Panel or ItemsControl, it'll expose the property named Children to other developers. So in this case, deriving from Control is a better idea, right?
Note 3: This imagined picture wall control has its own default way of loading certain pictures (for example, pulling pictures from a server) and it does not want this way to be messed around. If this is the case, then we should not inherit ItemsControl, right?
Panel is a container that is used to arrange its children. For example: Grid with a title and one button on the bottom and an image on center - Grid is very flexible to help you move stuff and arrange them when you change the size of window etc.
ItemsControl is a control that helps you with a collection of items. Let's take a concrete example: Listbox. You can very easly show a list of items, applay template to all of them, so on and so forth.
Control class is basically a UI element that can have its own template.
Note that, it is a way much better to define own UserControl, edit template or style of your PictureWall, insted of subclassing (there are many advantages, for example you can use Blend to redefine the style).
Edit:
# note2
If I were you I would make my own User Control to reuse existing controls to make what I want. If that won't be enough I would subclass Control.
[StyleTypedProperty(Property = "FooStyle", StyleTargetType = typeof(Control))]
public partial class MyDangControl: Control
{
...
# note3
This is a bad idea to combine all in one. You should split the logic that fetch the data form yout Picture Wall. For instance, user presses thumbnail to download the image and whole UI hangs. Horrible UX.
To be crystal clear, let me quote Pro WPF in C# 2010
Control
This is the most common starting
point when building a control
from scratch. It’s the base class for
all user-interactive widgets. The
Control class adds properties for
setting the background and foreground,
as well as the font and alignment of
content. The control class also places
itself into the tab order (through the
IsTabStop property) and introduces the
notion of double-clicking (through the
MouseDoubleClick and
PreviewMouseDoubleClick events). But
most important, the Control class
defines the Template property that
allows its appearance to be swapped
out with a customized element tree for
endless flexibility.
ContentControl
This is the base class for controls
that can display a single piece of
arbitrary content. That content can be
an element or a custom object that’s
used in conjunction with a template.
(The content is set through the
Content property, and an optional
template can be provided in the
ContentTemplate property.) Many
controls wrap a specific, limited type
of content (like a string of text in a
text box). Because these controls
don’t support all elements, they
shouldn’t be defined as content
controls.
ItemsControl
ItemsControl is the base class for
controls that wrap a list of items but
don’t support selection, while
Selector is the more specialized base
class for controls that do support
selection. These classes aren’t often
used to create custom controls,
because the data templating features
of the ListBox, ListView, and TreeView
provide a great deal of flexibility.
Panel
This is the base class for controls
with layout logic. A layout control
can hold multiple children and
arranges them according to specific
layout semantics. Often, panels
include attached properties that can
be set on the children to configure
how the children are arranged.
They both can be used to display elements, but really an ItemsControl offers much more functionality. In addition, an ItemsControl doesn't really display it's elements, it leverages a Panel to do that.
An ItemsControl can display a list of items, which may or may not be UIElements/Visuals. The items can be templated using a configurable DataTemplate, which ultimately determines how the item is displayed. In addition, then items can be bound to an observable collection so it will automatically update.
Neither of these features are supported by a Panel. DataTemplates can be used, but you have to manually create an associated ContentControl/ContentPresenter and add it to your panel.
Ultimately, their functions are different. A Panel is used to display UIElements/Visuals. An ItemsControl is used to display any type of data and apply templates as needed.
I have a group of controls that look like this:
<Link to Image>
that i reuse a number of times. It's really simple a listview, 3 buttons and some layout panels.
I want to turn this into a reusable component but the columns in the listview can change and the sources they are bound to will change.
How do i go about this? i've seen many comparisons between ContentTemplates and UserControls etc but they never seem to be functional (eg Add will raise an event which i'll have to handle to add something to the listview, remove will raise an event where i'll likely ask if they are sure first).
I've accomplished the events with my own UserControl, but can't pass a list of GridViewColumns to the control. It also means i have to expose SelectedItem etc manually from the UserControl. Subclassing Listview seems promising for setup and access but doesn't conceptually seem right to have other controls in the listview area.
What is the right way?
I would definately recommend a UserControl. You should:
Add the controls you require to your user control
Add the Dependency Properties you require to your user control which allow you to configure it, e.g. SelectedItem
Wire up these dependency properties to the various controls within your user control. An easy way to do this is to set the DataContext of your user controls visual tree to the user control itself, e.g. if you have a Grid as the root for your user controls, set its DataContext = this in code. You can then use TwoWay bindings to connect up the various control properties to the user control properties.