XAML base class: user control, vs other control - wpf

What are the benefits and downsides of implementing a custom control in XAML by inheriting from UserControl:
<UserControl x:Class="MyButton" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Button>
<!-- custom content here -->
<!-- custom behaviors in the code behind -->
</Button>
</UserControl>
vs inheriting from the control I'm putting inside the UserControl?
<Button x:Class="MyButton" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- custom content here -->
<!-- custom behaviors in the code behind -->
</Button>

There is no benefit to using a UserControl if you really want a Button. A UserControl just provides a simple way to create a control. From the UserControl Class page on MSDN:
If you do need to create a new control, the simplest way is to create a class that derives from UserControl. Before you do so, consider that your control will not support templates and therefore will not support complex customization. However, deriving from UserControl is a suitable model if you want to build your control by adding existing elements to it, similar to how you build an application, and if you do not need to support complex customization. (If you want to use templates with your control, derive from Control instead.)
As the remarks from MSDN note, using UserControl instead of Button as your base class will mean that your control cannot be templated, whereas when using a Button as the base class, you could still provide a new ControlTemplate.
You should always use the control that most closely suits your needs as the base class. The UserControl is only there to provide an easy way for us to add a collection of already existing controls to the UI. If that is not what you want to do, then don't use it.

Related

Use properties of the base control that is inside the UserControl

How can I use the properties of the controls that are inside a user control without having to use DependencyProperty?
Since, if for example I want to use all the properties of a button, I would have to declare all these?
And if there is another way without user control and it is the correct one, I would appreciate it if you answered it. (Google translator, sorry)
UserControl:
<UserControl x:Class="UserControls.UserControl01"
...
>
<Grid>
<Button x:Name="uc_btn" />
<TextBox x:Name="uc_txt" />
<DataGrid x:Name="uc_dtg" />
</Grid>
</UserControl>
Code using the UserControl:
<Window x:Class="UserControls.wnd02"
...
>
<Grid>
<local:UserControl01 uc_btn.Background="Red" uc_txt.Margin="10" uc_dtg.BorderThickness="5" Margin="90" />
<local:UserControl01 uc_btn.Background="Green" uc_txt.Margin="25" uc_dtg.BorderThickness="20" Margin="5" />
</Grid>
</Window>
It is not usual to do what you are asking.
Let's consider a usercontrol which is intended to work as if it is one single control. For example a time picker. This contains two sliders which increase/decrease hour and minute. You can also overtype in the hour and minute textboxes and there's a : between the two textboxes.
This usercontrol is all about the one property though. Time. You don't care what the minutes background is externally. If this changes it's internal to the usercontrol.
In this scenario you'd usually add a TimeSpan dependency property to the usercontrol and this is the only thing anything external to it uses.
Pretty much all commercial WPF development uses the MVVM pattern and that TimeSpan would be bound to a property in the parent view's viewmodel.
That's one scenario.
Another is where a usercontrol encapsulates a bunch of UI which is then re-usable.
Styling has scope so when you apply a style to say a Button in a window then that would apply to any Buttons in a usercontrol within it. Setting their properties.
There are also certain dependency properties marked as "inherits" whose values propogate down the visual tree.
One such is DataContext and it is this which most teams would use to deal with properties within a usercontrol.
Using MVVM there would be a MainWindowViewModel.
That would have (say ) a ChildUserControlViewModel property. That would be associated with usercontrol using a datatemplate specified datatype.
You'd then bind properties of whatever is in a usercontrol to properties of ChildUserControlViewModel or properties of MainWindowViewModel using RelativeSource binding.
ViewModel first is a common navigation and composition pattern for WPF. You should be able to find numerous blogs explain it better than I can in a SO post.
Here's one:
https://social.technet.microsoft.com/wiki/contents/articles/30898.simple-navigation-technique-in-wpf-using-mvvm.aspx

Using custom control's alias in XAML

In a WPF (Silverlight) UserControl I have lots of custom control instances:
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:My="clr-namespace:MyProject;assembly=MyAssembly" Name="uc1" >
...
<Grid x:Name="grid1">
...
<My:CustControl x:Name="name1" />
<My:CustControl x:Name="name2" />
<My:CustControl x:Name="name3" />
...
</Grid>
In MyProject I have not only the CustControl implemented, but also the CustControl1, the CustControl2, the CustControl3 and the like. Sometimes, I have to use another custom control type in the UserControl. Can I have only one place for changing custom control's name instead of changing it in all the numerous references in the XAML?
In other words, can I use an alias for those multiple custom control references inside my XAML and one place where I define the real CustomControl class' name for that alias?
Or maybe some other approach for solving this problem?
You could write a simple empty wrapper class, which would inherit the control you currently use. Then in XAML you would use this wrapper instead of the specific CustControl. At any time, you could change the base class for the wrapper at one single place.
But I must say: this design stinks. Are you sure you couldn't solve this issue with global styles/templates for one CustControl class?

Hide control within a WPF User Control Library

I've a project made from the "WPF User Control Library" Template in Visual Studio.
This project contains one main usercontrol plus additional Windows/Usercontrols.
How can I "hide" these additional Windows/Usercontrols, so that the user can only import the main usercontrol from the assembly (I wanted to put a screen-shot to illustrate my question but unfortunately, my "reputation" is too low!).
Thx All
Fred
Make those controls internal. If you have classic UserControls with XAML and codebehind you will need to add x:ClassModifier="internal" to the root element in the XAML:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MyNameSpace.MyUserControl"
x:ClassModifier="internal">
<!-- bla -->
</UserControl>
Maybe the usage of attributes will solve your problem. There is one attribute "DesignTimeVisible" inside the ComponentModel namespace. If you put such an attribute right above your class implementation and set it to false, the corresponding control should not be visible in the designers toolbox.
I believe that x:ClassModifier="internal" will make the entire user control internal. This may not be desirable.
Instead if you add x:FieldModifier="private" to those controls within the user control that you don't wish to be accessible to the UserControl consumer, the generated C# will have those controls as private. Note the use of lower case which is correct for a C# field modifier.

Is it possible to include Xaml resources in a ControlTemplate?

I'm working on a Silverlight templated control (i.e. it derives from Control and has its look implemented as a ControlTemplate in generic.xaml) and came across the need for a ValueConverter in one of my bindings. Normally I'd just create an instance of the ValueConverter in the Resources of the control working with but I can't figure out how to do that with a ControlTemplate. I'd like to keep this implementation all in Xaml if possible, but I suppose I could override OnApplyTemplate and manually create the binding with a converter.
This does work in Silverlight 3. You just need to add a resources section inside your Control Template, and add the ValueConverter to the template's resources:
<ControlTemplate TargetType="controls:MyControl">
<Grid Margin="8,40,8,20" x:Name="peopleListContainer">
<Grid.Resources>
<controls:MyValueConverter x:Key="converter" />
</Grid.Resources>
<!-- ....
However, ValueConverters are often misused in Control Templates. You may want to use a TypeConverter instead. Bryant Likes wrote a good article discussing the difference between ValueConverter and TypeConverter in this scenario.

Is it possible to set code behind a resource dictionary in WPF for event handling?

Is it possible to set code behind a resource dictionary in WPF. For example in a usercontrol for a button you declare it in XAML. The event handling code for the button click is done in the code file behind the control. If I was to create a data template with a button how can I write the event handler code for it's button click within the resource dictionary.
I think what you're asking is you want a code-behind file for a ResourceDictionary. You can totally do this! In fact, you do it the same way as for a Window:
Say you have a ResourceDictionary called MyResourceDictionary. In your MyResourceDictionary.xaml file, put the x:Class attribute in the root element, like so:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MyCompany.MyProject.MyResourceDictionary"
x:ClassModifier="public">
Then, create a code behind file called MyResourceDictionary.xaml.cs with the following declaration:
namespace MyCompany.MyProject
{
partial class MyResourceDictionary : ResourceDictionary
{
public MyResourceDictionary()
{
InitializeComponent();
}
... // event handlers ahead..
}
}
And you're done. You can put whatever you wish in the code behind: methods, properties and event handlers.
== Update for Windows 10 apps ==
And just in case you are playing with UWP there is one more thing to be aware of:
<Application x:Class="SampleProject.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:rd="using:MyCompany.MyProject">
<!-- no need in x:ClassModifier="public" in the header above -->
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- This will NOT work -->
<!-- <ResourceDictionary Source="/MyResourceDictionary.xaml" />-->
<!-- Create instance of your custom dictionary instead of the above source reference -->
<rd:MyResourceDictionary />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
I disagree with "ageektrapped"... using the method of a partial class is not a good practice. What would be the purpose of separating the Dictionary from the page then?
From a code-behind, you can access a x:Name element by using:
Button myButton = this.GetTemplateChild("ButtonName") as Button;
if(myButton != null){
...
}
You can do this in the OnApplyTemplate method if you want to hookup to controls when your custom control loads. OnApplyTemplate needs to be overridden to do this. This is a common practice and allows your style to stay disconnected from the control. (The style should not depend on the control, but the control should depend on having a style).
Gishu - whilst this might seem to be a "generally not to be encouraged practice" Here is one reason you might want to do it:
The standard behaviour for text boxes when they get focus is for the caret to be placed at the same position that it was when the control lost focus. If you would prefer throughout your application that when the user tabs to any textbox that the whole content of the textbox was highlighted then adding a simple handler in the resource dictionary would do the trick.
Any other reason where you want the default user interaction behaviour to be different from the out of the box behaviour seems like good candidates for a code behind in a resource dictionary.
Totally agree that anything which is application functionality specific ought not be in a code behind of a resource dictionary.
Adding on....these days, with the advent of {x:Bind ...}, if you want to put your DataTemplate into a shared ResourceDictionary file, you are required to give that file a code behind.
XAML is for constructing object graphs not containing code.
A Data template is used to indicate how a custom user-object is to be rendered on screen... (e.g. if it is a listbox item) behavior is not part of a data template's area of expertise. Redraw the solution...

Resources