Hide control within a WPF User Control Library - wpf

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.

Related

Using a UserControl type vs a control's concrete type

Okay, I understand what a UserControl is and how they can be shared across multiple Windows/Views to share functionality, etc. Though, what is the benefit of using a UserControl type? It seems a lot cleaner if you were to use the root control instead of wrapping it inside a UserControl.
Example:
<UserControl>
<Grid>
//...
<Grid/>
</UserControl>
vs.
<Grid>
//...
</Grid>
Using the root control also has the benefit if reducing the VisualTree.
UserControl has some properties it inherits from ContentControl, like ContentTemplate, ContentTemplateSelector, some other stuff. If you don't need those, you can create a user control, change the outermost element to Grid and change its base class to Grid in the .xaml.cs, and it'll compile. At least with the trivial example I just tried, it works fine.
However, unless you've identified some concrete problem being created by UserControl in your application, I can't see any reason to go to the trouble. But go ahead, if you like doing things that way.

XAML base class: user control, vs other control

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.

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?

Using XAML + designer to edit Plain Old CLR Objects?

I want to write a POCO in XAML, and use a DataTemplate to display that object in the GUI at runtime. So far, so good; I know how to do all that.
Since I'll already have a DataTemplate that can transform my POCO into a WPF visual tree, is there any way to get the Visual Studio designer to play along, and have the Design View show me the POCO+DataTemplate's resulting GUI, as I edit the POCO's XAML? (Obviously the designer wouldn't know how to edit the "design view"; I wouldn't expect the Toolbox or click-and-drag to work on the design surface. That's fine -- I just want to see a preview as I edit.)
If you're curious, the POCOs in question would be level maps for a game. (At this point, I'm not planning to ship an end-user map editor, so I'll be doing all the editing myself in Visual Studio.) So the XAML isn't WPF GUI objects like Window and UserControl, but it's still not something where I would want to blindly bang out some XAML and hope for the best. I want to see what I'm doing (the GUI map) as I'm doing it.
If I try to make a XAML file whose root is my map object, the designer shows "Intentionally Left Blank - The document root element is not supported by the visual designer." It does this even if I've defined a DataTemplate in App.xaml's <Application.Resources>.
But I know the designer can show my POCO, when it's inside a WPF object. One possible way of accomplishing what I want would be to have a ScratchUserControl that just contains a ContentPresenter, and write my POCO XAML inside that ContentPresenter's Content property, e.g.:
<UserControl ...>
<ContentPresenter>
<ContentPresenter.Content>
<Maps:Map .../>
</ContentPresenter.Content>
</ContentPresenter>
</UserControl>
But then I would have to be sure to copy the content back out into its own file when I was done editing, which seems tedious and error-prone, and I don't like tedious and error-prone. And since I can preview my XAML this way, isn't there some way to do it without the UserControl?
I'm doing this right now, actually. Create a ResourceDictionary and reference it from the other XAML file. For example, make one file containing you plain old object, i.e.:
<Windows:ResourceDictionary>
<Collections:ArrayList x:Key="PreferenceList">
<NumericPreference id="server.port"
helpText="The port on which the server should listen for incoming connections (default is 30588)"
min="1"
max="65535"
step="1"
displayName="Port"
validationName="Port number" />
</Collections:ArrayList>
</Windows:ResourceDictionary>
(where NumericPreference is replaced by your POCO), and then reference it like so:
<UserControl>
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Preferences.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<!-- Your code here -->
</Grid>
</UserControl>
... But yes, you'd still need your "scratch user control" hooked up to it to see the designer result, but there's no copying and pasting involved. The key part here is the ResourceDictionary Source="YourStaticResource.xaml"
You can't have the map as the root element (the root element must be ResourceDictionary), but you can have it as the only child element of the ResourceDictionary.
To reference the resource, use, of course {StaticResource XXX} or {DynamicResource XXX} where XXX is the x:Key you gave the POCO in its XML file (in this case I gave the referenced POCO object, the ArrayList, the "PreferenceList" key)
I'm fairly certain that you aren't going to get what you want here.
WPF won't process much in the way of logic in the design window. That includes (for the most part) DataTemplate and IValueConverter objects that you use in your XAML data bindings, since those objects usually work with (POCO) objects that are not instantiated until run-time.
This could explain why it works in the UserControl example, since you ARE clearly creating an instance of your Map POCO right there in the XAML. The designer window absolutely will not attempt to render anything that is based on bindings or templates that refer to objects that Visual Studio can't instantiate at design-time. This basically means that you can't have your objects show up in the design window if you are trying to create those objects in your C# (or whatever) code behind the scenes. Your back-end code cannot be run by the design window, because it has to be built by the compiler and run before any of it can execute. (Previous versions of Visual Studio use extreme workarounds to try and remedy this, and Microsoft no longer provides this support.) Markup languages like XAML don't have that restriction since they contain no logical execution sequence, so the design window can render them on the screen using only the parsed XAML markup.
In a nut-shell, I don't think the XAML design window was ever intended to be used the way you are trying to use it.
If you really want to be able to see your POCO in the designer, but you don't want to have to insert it into a UserControl with a ContentPresenter --- try deriving your POCO from an appropriate root-element that the designer can render, and adding a Serialize method to read/write it to/from files.
If these solutions don't work for you, then you are probably going to have to deal with Visual Studio not rendering your Map objects in the design window. Maybe this will give you some motivation to create that stand-alone map editor after all, even if you don't ship it out to the end-user. You may want to spend the time to write a simple editor, even if it's for your use only. Visual Studio won't replace your custom map editor - at least, not in any way that will be useful to you.

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