Disambiguation between two namespaces in separate assemblies in Xaml - wpf

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.

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.

Metro Style in WPF applications _ Packages differences

I want to create a metro style application, I did some researches and I found lots of articles and tutorials about that.
But I still need a clear comparison between Modern UI for WPF , Elysium and MahApps.
Testing all of them takes too much time ! I need to learn bout each one's features to decide with which one to start.
Thanks,
first : Download the WPF Shell Integration Library Here
then use this XML Code :
<Window x:Class="MyLibrary.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:shell="http://schemas.microsoft.com/winfx/2006/xaml/presentation/shell"
Title="MainWindow"
WindowStyle="SingleBorderWindow"
ResizeMode="CanResizeWithGrip"
mc:Ignorable="d"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="449"
d:DesignWidth="677"
Foreground="White"
removed="Black">
<shell:WindowChrome.WindowChrome>
<shell:WindowChrome CaptionHeight="35"
GlassFrameThickness="0,0,0,1"
ResizeBorderThickness="5" />
</shell:WindowChrome.WindowChrome>
<Grid x:Name="LayoutRoot">
</Grid>
</Window>
(note, you need to have referenced Microsoft.Windows.Shell)
This is really the Best way to do that.. It will work on all windows versions.
Edit:
if you want to add Caption Buttons on the top of the window add this XAML code to any control at the top: (button as example)
<button shell:WindowChrome.IsHitTestVisibleInChrome="True"/>

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)

XAML namespace naming conventions

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.

Setting design time DataContext on a Window is giving a compiler error?

I have the following XAML below for the main window in my WPF application, I am trying to set the design time d:DataContext below, which I can successfully do for all my various UserControls, but it gives me this error when I try to do it on the window...
Error 1 The property 'DataContext' must be in the default namespace or in the element namespace 'http://schemas.microsoft.com/winfx/2006/xaml/presentation'. Line 8 Position 9. C:\dev\bplus\PMT\src\UI\MainWindow.xaml 8 9 UI
<Window x:Class="BenchmarkPlus.PMT.UI.MainWindow"
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:UI="clr-namespace:BenchmarkPlus.PMT.UI"
xmlns:Controls="clr-namespace:BenchmarkPlus.PMT.UI.Controls"
d:DataContext="{d:DesignInstance Type=UI:MainViewModel, IsDesignTimeCreatable=True}"
Title="MainWindow" Height="1000" Width="1600" Background="#FF7A7C82">
<Grid>
<!-- Content Here -->
</grid>
</Window>
I needed to add the mc:Ignorable="d" attribute to the Window tag. Essentially I learned something new. The d: namespace prefix that Expression Blend/Visual Studio designer acknowledges is actually ignored/"commented out" by the real compiler/xaml parser!
<Window
...
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
...
/>
The following was taken from
Nathan, Adam (2010-06-04). WPF 4 Unleashed (Kindle Locations 1799-1811). Sams. Kindle Edition.
Markup Compatibility
The markup compatibility XML namespace (http://schemas.openxmlformats.org/markup-compatibility/2006, typically used with an mc prefix) contains an Ignorable attribute that instructs XAML processors to ignore all elements/attributes in specified namespaces if they can’t be resolved to their .NET types/members. (The namespace also has a ProcessContent attribute that overrides Ignorable for specific types inside the ignored namespaces.)
Expression Blend takes advantage of this feature to do things like add design-time properties to XAML content that can be ignored at runtime.
mc:Ignorable can be given a space-delimited list of namespaces, and mc:ProcessContent can be given a space-delimited list of elements. When XamlXmlReader encounters ignorable content that can’t be resolved, it doesn’t report any nodes for it. If the ignorable content can be resolved, it will be reported normally. So consumers don’t need to do anything special to handle markup compatibility correctly.
Wow, what a pain! Let's hope MS puts in some VS design-time support for x:Bind.
We to be able to use the VS designer but also be able to switch easily to x:Bind instead of Binding. Here's what I did:
In my View, I added a property to get my ViewModel. This makes sense because x:Bind paths are relative to the Page (i.e. the View object).
In my Page XAML, I added the following to the <Page ... > at the top of the XAML:
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=local:MyView, IsDesignTimeCreatable=False}"
DataContext="{x:Bind}"
This way, the Page's actual data context is set to the Page itself due to the {x:Bind}. That's because x:Bind is relative to the Page and there is no path given.
At the same time, due to the d:DataContext line, the VS designer reflects on the MyView class (without creating an instance) for the purpose of the VS designer interaction. This lets VS design from MyView, where you can then scroll down to the ViewModel property, expand it and select the item that you want to bind to.
When you do all that, the VS designer will create a Binding statement whose path is relative to the View, i.e. it happens to be exactly the same as the path that x:Bind expects. So, if you want to switch to x:Bind later on, you can just search and replace all "{Binding" with "{x:Bind".
Why do we even need the d:DataContext line to tell VS what class to look at? Good question, since you would think that VS could figure out the very next line sets the DataContext to the Page, using DataContext={x:Bind}. Go ahead and try it, it does not work and neither does it work if you change x:Bind to Binding relative to self.
Hopefully this situation will get cleaned up by MS !!
If you are not tooo fussy on the data have a look at the sample data found in xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
You use it like this...
<ItemsControl ItemsSource="{Binding Path=Report.Audit.Data}" d:ItemsSource="{d:SampleData}" Grid.Row="1">
<ItemsControl.ItemTemplate>
<DataTemplate>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
it then renders the items control with a few rows of data
I've solved the problem adding d:DataContext="{d:SampleData}" in the component definition (UserControl or Window).
<UserControl x:Class="TestControl"
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:local="clr-namespace:TestApp.Views"
DataContext="{Binding TestViewModel}"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:SampleData}"
>

Resources