WPF - How to extend an existing toolbar UserControl - wpf

I create a new UserControl for reuse. The UserControl contains a toolbar with several Buttons.
When I use the UserControl, I hope I can add additional Buttons on it but can not modified the orginal ones.
This is easily implemented in WinForm by inheritance. But in WPF, I have no idea how to do it.

There is a few ways to do what you need.
For example, your UserControl could expose ICollection TabButtons property, which is ItemsSource for toolbar. In this case, your toolbar should contain some ItemsControl to host buttons and should be binded to aforementioned TabButtons property.
And TabButton struct should describe all needed information (for example, properties Header, Icon, ToolTip and Command).
Or you could provide appropriate methods: AddToolbarButton(), RemoveToolbarButton(). This methods change TabButtons collection (but the collection itself cann't be accessed from outer realm).

Related

How to identify whether a WPF Control is a Container control?

At runtime I am creating a WPF control. It can be any WPF Control.
I want to find out whether this WPF Control, IS A CONTAINER CONTROL.
i.e. can this control can embed/contain another control.
Does there exist any Attribute through which the above can be achieved?
e.g. a label, panel, groupBox can contain other control like button, but textBOX cant.
In WPF there are a few base classes that controls extend from.
ContentControl: Most controls extend from this because most controls can store some type of single content within them.
ItemsControl: These are types of collection controls, which contain a collection of content within them.
Panel: These are special controls for layouts. They implement the ArrangeOverride and MeasureOverride methods to measure/arrange the children controls within them. Most of them also expose attached properties for best use.
That being said, you would typically want to use the is operator to check if your control inherits from what you intend it to. You can be specific or general, but typically you want to be as general as possible. I'm not sure what you meant by "container", which is why I listed the three (3) typical base controls that could contain other controls. For example:
if (myControl is ContentControl)
{
// Do something here.
}
All the controls mentioned here and here apart from TabControl inherit from Panel
So you can do something like:
if (myControl is Panel || myControl is TabControl)
{
// Then it's a container
}

How to clone a WPF grid with all children?

I have several controls in my WPF window. I have divided the window into 4 sections. If I click on the section in the upper left, I want to copy the contents of this section in another window popup.
What I want to copy is a grid that can contain a lot of different controls, ex: togglebutton, button, panel... derived from ItemsControl, Control... and with DependencyProperty, ObservableCollection etc..
I tried :
XamlWriter.Save(data);
XamlServices.Save(data);
but I always have these errors :
Cannot serialize a generic type 'System.Collections.ObjectModel.ObservableCollection`1 or
A BadImageFormatException has been thrown while parsing the signature. This is likely due to lack of a generic context. Ensure
genericTypeArguments and genericMethodArguments are provided and
contain enough context.
You should not clone XAML itself, this is brutal and wrong way.
Take a look at the possible MVVM solution below. Let's say single DataGird represents a single business Item, so you need following:
ItemsWindow.xaml - represents a ListView and single item of ListView is DataGrid representing an item details
ItemsViewModel - expose list of Item objects (ObservableCollection<Item> Items { get; set; })
Each item of the ItemsWindow.ListView is represented by a DataTemplate like ItemDataTemplate
ItemsViewModel exposed command ICommand CopyItem and in command handler actually copyiing only instance of the Item business entity and adding it to the Items list, WPF reflects this changes via bindings and UI will be updated by a new ListViewItem with a DataGrid representing a details of just copied Item
Useful links:
Model View ViewModel pattern
Commands
Data Templating Overview - short and clean overview of WPF data templates with examples

In WPF (or silverlight or WP7), should a picture wall derive from ItemsControl or Panel?

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.

WPF Control Grouping

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.

Difference between Control Template and Data Template in wpf

Can someone elaborate the difference between ControlTemplate and DataTemplate in wpf?
What should one use in case of custom controls? Like for example a StackPanel which possibly has an image and a TextBox?
It seems confusing in some cases where you define a custom control using the 'Content' property.
It would be great if an example of how each can be used in different scenarios can be provided.
A ControlTemplate is used to change the look of an existing control. So if you don't want your buttons to look rectangular, you can define a control Template which makes them look oval or any irregular shape. It's a way to customize 'look-less' stock WPF controls ; an alternative to writing your own user-controls. More details
A DataTemplate is used to specify how an instance of a specific class (usually a Data Transfer object - an object with properties) is to be rendered visually. e.g. define a DataTemplate to visualize a Customer instance in a listbox displaying all customers. More details

Resources