XAML namespace naming conventions - wpf

I have a C# WPF project, namespaced test. How should I name sub-namespaces in XAML?
<Window x:Class="test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:test"
xmlns:local.c="clr-namespace:test.Converters"
xmlns:local.v="clr-namespace:test.Validators"
Title="MainWindow" Height="360" Width="640"> ....
Here I have a convention of separating the sub-packages with a period.. Is it okay?
Kind regards,
e.

A better practice, if possible, would be to separate the C# namespaces that you use from the WPF namespaces. This will also reduce the number of imports that you have. This can be done thanks to the XmlnsDefinition class.
<Window x:Class="test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:test="http://whatever.com/test">
In the AssemblyInfo.cs of your libraries, you'll just need to add:
[assembly: XmlnsDefinition("http://whatever.com/test", "test")]
[assembly: XmlnsDefinition("http://whatever.com/test", "test.Converters")]
[assembly: XmlnsDefinition("http://whatever.com/test", "test.Validators")]
[assembly: XmlnsDefinition("http://whatever.com/test", "test.CustomControls")]
Note that this will only work if the classes are in a different assembly to the one you are referencing them from. Within the same assembly, you'll still need to use the C# namespaces.
You can even eliminate the imports altogether by adding your namespaces to the WPF XML namespace:
[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "test")]
[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "test.Converters")]
[assembly: XmlnsDefinition("http://schemas.microsoft.com/winfx/2006/xaml/presentation", "test.Validators")]
That allows people to write:
<Window x:Class="test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<!-- Note: no namespace prefix needed! -->
<YourCustomControl />

The typical WPF application really doesn't have a namespace convention for the XAML, other than the default xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml", the Blend design time namespace and xmlns:local which will typically refer to the current namespace.
In the scenario you described above, I've seen/used a few variants, i.e.,
<Window x:Class="test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:test"
xmlns:c="clr-namespace:test.Converters"
xmlns:v="clr-namespace:test.Validators">
or
<Window x:Class="test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:test"
xmlns:conv="clr-namespace:test.Converters"
xmlns:val="clr-namespace:test.Validators">
In the end, it's really up to whatever you and your team agree upon.

Related

Can I get rid of xmlns tags (and maybe also resources) from my all user controls by using style/resource?

I would like to get rid of xmlns tags from every UserControl or Window file.
Can I do it by using styles or resources somehow?
Many of my user controls look like this:
<UserControl x:Class="Mst2.View.Controls.Modules.TimerEntryControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:bcp="clr-namespace:ABitOfBinding"
xmlns:dc="clr-namespace:Mst2.Dictionaries"
xmlns:vm="clr-namespace:Mst2.ViewModel"
xmlns:vc="clr-namespace:Mst2.ValueConverters"
xmlns:c="clr-namespace:Mst2.View.Controls"
xmlns:mw="clr-namespace:Mst2.View.Windows"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<dc:Mst2Dictionaries x:Key="Dictionaries" />
<bcp:ByteBit2Bool x:Key="ByteBit2Bool" />
<BooleanToVisibilityConverter x:Key="BoolToVis" />
<vc:TimerTimeAndRangeConverter x:Key="TimerTimeAndRangeConverter"/>
</UserControl.Resources>
<!-- user control contents here -->
</UserControl>
If you instantiate resources from a specific namespace, it has to be declared. How would the parser know which type you are referring to? However, if these resources are located in a separate assembly, you can create a custom XAML namespace and map all of your CLR namespaces to it. This does not work if the resources and namespaces are defined in the same assembly.
Mapping CLR Namespaces to XML Namespaces in an Assembly
Add an XmlnsDefinition attribute for each CLR namespace with your desired XML namespace.
Specifies a mapping on a per-assembly basis between a XAML namespace and a CLR namespace, which is then used for type resolution by a XAML object writer or XAML schema context.
The XmlnsDefinitionAttribute takes two parameters: the XML/XAML namespace name, and the CLR namespace name. More than one XmlnsDefinitionAttribute can exist to map multiple CLR namespaces to the same XML namespace.
You need to insert the attribute at assembly level, so you have to own or be able to modify it.
This attribute, XmlnsDefinitionAttribute, is placed at the assembly level in the source code that produces the assembly.
For example for your Mst2 assembly, the attributes in AssemblyInfo.cs could look like below. You are free to choose the URI, it does not have a special meaning here beyond being an identifer.
[assembly: XmlnsDefinition("http://schemas.Mst2.com/2021", "Mst2.Dictionaries")]
[assembly: XmlnsDefinition("http://schemas.Mst2.com/2021", "Mst2.ViewModel")]
[assembly: XmlnsDefinition("http://schemas.Mst2.com/2021", "Mst2.ValueConverters")]
[assembly: XmlnsDefinition("http://schemas.Mst2.com/2021", "Mst2.View.Controls")]
[assembly: XmlnsDefinition("http://schemas.Mst2.com/2021", "Mst2.View.Windows")]
Additionally, you could define an XmlPrefix which is a hint to the designer to use this prefix when adding the XAML namespace to your XAML file.
[assembly: XmlnsPrefix("http://schemas.Mst2.com/2021", "mst2")]
Please note that this is respected by designers like in Visual Studio, but others might not.
Identifies a recommended prefix to associate with a XAML namespace for XAML usage, when writing elements and attributes in a XAML file (serialization) or when interacting with a design environment that has XAML editing features.
XAML processors or frameworks that incorporate XAML, or any process that performs XAML serialization, should generally honor the recommended prefix.
When consuming the namespace in your control (in a different assembly), it would look like this.
<UserControl x:Class="Mst2.View.Controls.Modules.TimerEntryControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mst2="http://schemas.Mst2.com/2021"
xmlns:bcp="clr-namespace:ABitOfBinding"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<mst2:Mst2Dictionaries x:Key="Dictionaries" />
<mst2:ByteBit2Bool x:Key="ByteBit2Bool" />
<BooleanToVisibilityConverter x:Key="BoolToVis" />
<mst2:TimerTimeAndRangeConverter x:Key="TimerTimeAndRangeConverter"/>
</UserControl.Resources>
<!-- user control contents here -->
</UserControl>
Another thing you could do is to create a resource dictionary for shared resources, e.g.:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:bcp="clr-namespace:ABitOfBinding"
xmlns:dc="clr-namespace:Mst2.Dictionaries"
xmlns:vc="clr-namespace:Mst2.ValueConverters">
<dc:Mst2Dictionaries x:Key="Dictionaries" />
<bcp:ByteBit2Bool x:Key="ByteBit2Bool" />
<BooleanToVisibilityConverter x:Key="BoolToVis" />
<vc:TimerTimeAndRangeConverter x:Key="TimerTimeAndRangeConverter"/>
</ResourceDictionary>
Then you can include it everywhere you need it without having to specify the namespace for each resource or redeclaring the resources each time.
<UserControl x:Class="Mst2.View.Controls.Modules.TimerEntryControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:bcp="clr-namespace:ABitOfBinding"
xmlns:vm="clr-namespace:Mst2.ViewModel"
xmlns:mw="clr-namespace:Mst2.View.Windows"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<ResourceDictionary>
<BooleanToVisibilityConverter x:Key="BoolToVis" />
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MySharedResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<!-- User control contents here -->
</UserControl>
If these are common resources you could also simply add them to the application resource dictionary, then they would be available in each control, without any further ado.

Can MahApps.Metro be used in MvvmCross?

I was trying to use Mahapps Metro inside a WPF project using MvvmCross mvvm framework.
Both seem to use custom window control. Is there a way to use both in a project?
Metro window:
<mah:MetroWindow x:Class="TipCalc.WPF.MainWindow"
xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TipCalc.WPF"
xmlns:views="clr-namespace:MvvmCross.Platforms.Wpf.Views;assembly=MvvmCross.Platforms.Wpf"
mc:Ignorable="d"
Title="MainWindow"
Height="450"
Width="800">
<Grid>
</Grid>
</mah:MetroWindow>
MvvmCross Window:
<views:MvxWindow x:Class="TipCalc.WPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TipCalc.WPF"
xmlns:views="clr-namespace:MvvmCross.Platforms.Wpf.Views;assembly=MvvmCross.Platforms.Wpf"
mc:Ignorable="d"
Title="MainWindow"
Height="450"
Width="800">
<Grid>
</Grid>
</views:MvxWindow>
The application runs either way. But with the Metro window in place, the rest of the application doesn't get set up(ie.-children views). With the MvvmCross window in place, the application works as usual but is not designed or colored.
Since multi inheritance is not supported in C#, this is not possible out of the box.
But a look at the source code of MvxWindow shows it's no big class. So a potential solution could be creation of your own window. This window, let's call it MvxMetroWindow, could collect both functionalities by inheriting from MetroWindow and aditionally all the source code of MvxWindow added (copied from the original source code) by yourself.
This would look like this:
using System;
using System.Windows;
using MahApps.Metro.Controls;
using MvvmCross;
using MvvmCross.Binding.BindingContext;
using MvvmCross.Platforms.Wpf.Views;
using MvvmCross.ViewModels;
using MvxApplication = MvvmCross.Platforms.Wpf.Views.MvxApplication;
namespace TipCalc.WPF
{
public class MvxMetroWindow : MetroWindow, IMvxWindow, IMvxWpfView, IDisposable
{
private IMvxViewModel _viewModel;
private IMvxBindingContext _bindingContext;
private bool _unloaded = false;
//... Further implemenetation of original MvxWindow
}
}
The custom window finally can be used like this:
<local:MvxMetroWindow x:Class="TipCalc.WPF.MainWindow"
xmlns:local="clr-namespace:TipCalc.WPF"
...

XAML Syntax for Resource Double value

I'd like to define a static resource to be used for FontSize for multiple items, but I'd like to apply it to the page in which I'm defining it, so I have:
<Page x:Class="Sample1.JoggingPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:core="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:Sample1">
<Page.Resources>
<ResourceDictionary>
<core:Double x:Key="MainFontSize">28</core:Double>
</ResourceDictionary>
</Page.Resources>
<Page.FontSize>
What do I have to do here to use MainFontSize as the value??
</Page.FontSize>
I have tried everything I can think of and searched for a related answer, but I obviously don't have the important keywords to search for this.
Thank you in advance,
Chris

Disambiguation between two namespaces in separate assemblies in Xaml

I am re-developing a WPF application and the application makes use of the following 2 assemblies as it uses separate components from each:
WPFToolkit and PresentationFramework.
In my Xaml.cs I have used extern alias to use the namespace System.Windows.TemplateVisualState and that is all good and well, my question is in my Xaml.xaml, how would I differentiate between WPFToolkit.System.Windows.TemplateVisualState and PresentationFramework.System.Windows.TemplateVisualState?
Below is the top part of my Xaml:
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:toolkit="http://schemas.microsoft.com/wpf/2008/toolkit"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CAIS2"
xmlns:CodeLib="clr-namespace:CodeLib;assembly=CodeLib"
xmlns:CAISCommon="clr-namespace:CAISCommon;assembly=CAISCommon" >
Here is where Resharper is complaining:
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="LoginStates">
<Windows:VisualState x:Name="LoggedOut">
......
It looks like you've got a namespace set up for the WPF toolkit already, so can you not do it like:
<toolkit:VisualStateManager.VisualStateGroups>
<toolkit:VisualStateGroup x:Name="LoginStates">
<Windows:VisualState x:Name="LoggedOut">
I'm not too familiar with the consequences of using the extern alias method, so I don't know if that invalidates this at all.

Inconsistency between XAML intellisense and compiler for a control

I am converting some Silverlight XAML into WPF. I currently have a user control (MyControl) that is trying to include a couple of other controls that are custom buttons (MyButton1) that are within the same assembly. I have the following XAML that compiles and works in SL:
MyButton1
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="MyCompany.MyNamespace.MySubnamespace.MyButton1"
d:DesignWidth="640" d:DesignHeight="480">
...
</UserControl>
MyControl
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:somename="clr-namespace:MyCompany.MyNamespace.MySubnamespace;assembly=MyCompany.MyAssemblyName"
mc:Ignorable="d"
x:Class="MyCompany.MyNamespace.MySubnamespace.MyControl"
d:DesignWidth="640" d:DesignHeight="480">
<somename:MyButton1 />
</UserControl>
When I try to compile this code in WPF, I get the following error:
The tag 'MyButton1' does not exist in XML namespace 'clr-namespace:MyCompany.MyNamespace.MySubnamespace;assembly=MyCompany.MyAssemblyName.'
The weird thing is, if I comment out the <somename:MyButton1 /> line of code and compile and then type in <somename: IntelliSense gives me the option to autocomplete MyButton1. Which suggests that the control itself is in the assembly but for some reason it is not being seen when the MyControl XAML is being compiled.
For some context, I took the SL csproj file and made some modifications to it manually to make it a WPF csproj file. If there is a possibility that this caused this funkiness to happen, I'd be glad to share relevant portions of the project file.
Found the answer on an MSDN forum. Turns out that the assembly=MyCompany.MyAssemblyName line in my xmlns was screwing things up. Once I removed that line, I was able to reference the controls.
Related Link: http://social.msdn.microsoft.com/Forums/en/wpf/thread/807c9b80-81c7-4f75-aa2f-8427e17b1a90
To reference the current assembly you must not type its name but leave it blank, i.e. assembly=, the other option is of course to drop it completely. (MSDN -> Mapping to Current Assemblies)

Resources