XamlParseException thrown calling XamlReader.Load - wpf

I'm playing around with .net 4's System.Windows.Markup.XamlReader - just as an education exercise - and I keep bumping into the same problem: Loading xaml with XamlReader.Load throws a XamlParseException if the root object defines an x:Class, but successfully parses and loads the node if not.
Here's the code I'm trying:
using System.Windows;
using System.Xaml;
using XamlReader = System.Windows.Markup.XamlReader;
namespace WpfApplication2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// Load up UserControl1.xaml from the solution
var reader = new XamlXmlReader(#"../../UserControl1.xaml", XamlReader.GetWpfSchemaContext());
var userControl = XamlReader.Load(reader) as UserControl1;
// Do something with userControl...
}
}
}
I've tried XamlReader.Parse directly from a string holding the xaml with the same result: only works if no x:Class declaration is defined.
Removing the x:Class declaration doesn't seem like a good option, because then I lose the code-behind, specifically the call to InitalizeComponent()
The exception detail:
'Specified class name 'WpfApplication2.UserControl1' doesn't match actual root instance type 'System.Windows.Controls.UserControl'. Remove the Class directive or provide an instance via XamlObjectWriterSettings.RootObjectInstance.'
...but I don't know how (where) to set XamlObjectWriterSettings.RootObjectInstance (or indeed, if that's required?)
Any clues?

XamlReader is a parser, not a compiler, so doesn't support code-behind. If you need to associate code with your dynamically loaded XAML you can do something like wrapping it up into a control defined elsewhere that you can use an instance of in the XAML or, after reading in the XAML, connect up the code (i.e. event handlers) to elements in the resulting object.

You can't use x:Class in dynamic XAML. Instead what you can do is you can hook events after the loading XAML. please have a look at this link
Loading XAML XML through runtime?

Related

Inheriting from Window in WPF MVVM

I'm trying to implement the following solution: https://stackoverflow.com/a/1486481/154439. In the author's solution he writes,
I created an abstract ApplicationWindowBase class that inherits from Window.
I am not sure what he means here. I tried changing my XAML from <Window ... to <ApplicationWindowBase .... No luck.
The designer-generated file for the window inherits from System.Windows.Window, but as that file is designer-generated, making changes to it does me no good. I've tried various other approaches with no success.
I am very new to both WPF and MVVM. Am I missing something obvious?
Code to go along with Kevin's comment:
Code Behind
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : ApplicationWindowBase
{
public MainWindow()
{
InitializeComponent();
}
}
XAML
<myPrefix:ApplicationWindowBase x:Class="StackOverflow.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:myPrefix="clr-namespace:StackOverflow"
Title="TestWindow" Height="300" Width="300">
<Grid>
</Grid>
</myPrefix:ApplicationWindowBase>
Just make sure you use the correct namespace, mine happens to be StackOverflow.
First, xaml or not, these are all classes. Therefore, anything inheriting from another class (i.e., Window), must do so as any other class.
namespace SomeNamespace
{
public sealed class MyWindow : Window
{
public object SomeNewProperty {get;set;}
}
}
xaml is just a different type of serialization with its own set of rules. But it's still serialized XML, and as such everything must be traceable back to its original type.
How xaml does this is through a facility in XML called "namespaces". They fit well with our understanding of namespaces as C# developers, as we must map an XML namespace to a namespace in our application so that the xaml serializer can match an XML element with a CLR type.
Xaml uses a couple different ways of matching these namespaces. One looks like a URL and is defined by an assembly attribute (e.g., "xmlns="http://microsoft.com/whatevs"). This works when the assembly is external to the one you are writing in. In your case, you'll have to use the other method of identifying your namespace. This specialized XML namespace is parsed by the xaml serializer in order to identify the namespace and containing assembly of your classes. It goes by the form "clr-namespace:SomeNamespace;assembly=SomeAssembly". You can omit the assembly bit if the type is in the current assembly.
To put it all together with the above example, you would create an instance of your new window like this:
<t:MyWindow
xmlns:t="clr-namespace:SomeNamespace"
xmlns="the standard microsoft namespace here"
t:OmitOtherStuffBecauseThisIsAnExampleLol="true">

How can I access a resource from a ValueConverter?

I have a UserControl in a custom DLL assembly where I've defined two static BitmapImage resources that represent the state of data in our ItemsControl. I want to use a converter to set the Source property of an Image to one of the BitmapImage resources depending on some condition. However, I'm not sure how to access the resources from inside the Convert method since I don't have an instance of the control that I'm using the converter on.
I've tried loading the resources into static variables in a static constructor for the converter, which is also in the same DLL, but I haven't been successful.
This fails...
public class MyConverter : IValueConverter
{
static BitmapImage myFirstResource;
static MyConverter()
{
// This can't seem to find the resource...
myFirstResource = (BitmapImage)Application.Current.FindResource("MyResourceKey");
}
}
...but in the XAML, this succeeds, so I know the resource key is valid.
<Image Source="{StaticResource MyResourceKey}" />
I don't know if this makes any difference, but this is in a DLL, not in the EXE. Still, I thought all resources were flattened down to the application depending on where you were executing from.
Found perfect solution here Accessing a resource via codebehind in WPF
(better than using Application.Current)
#itsho
You can simply add x:Class to it:
<ResourceDictionary x:Class="Namespace.NewClassName"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<ds:MyCollection x:Key="myKey" x:Name="myName" />
</ResourceDictionary>
And then use it in code behind:
var res = new Namespace.NewClassName();
var col = res["myKey"];
Then a little fix should be applied:
#Stephen Ross
But to be able to find resources using it's key I had to call res.InitializeComponent() before attempting to access the key otherwise the object would show no keys and the call to res["myKey"] would return null

How to locate the source of a binding error?

How can I figure out what line of xaml contains the troublesome binding When my debug output is full of lines like the following:
System.Windows.Data Error: 5 : Value produced by BindingExpression is not valid for target property.; Value='UW.Entities.ProgramModel.UWProgram' BindingExpression:Path=; DataItem='RuntimeType' (HashCode=24995901); target element is 'DataGridCollectionViewSource' (HashCode=60976864); target property is 'Source' (type 'Object')
I don't know how to interpret this in a way that can let me find the responsible line of xaml. I can't even figure out what xaml file the error is coming from. Is there some way to get more information when these errors occur?
'UW.Entities.ProgramModel.UWProgram' is just a type - I don't know what the object being bound to is. I also have lots of DataGridCollectionViewSources in various bits of xaml, all who's property 'Source' is bound to something which may or may not have that type (again - no easy way to tell).
If you do not know which binding fails
I would use the Snoop utility for this purposes. In short - at the top-left corner above the visual tree, you'll find a drop-down list which allows filtering visuals, just select Visuals with binding Error. See online documentation for more details.
If you know which binding fails
Sometime you know which binding fails but was not able to find a source fo the problem since binding is pretty tricky, for instance TemplateBindings, bindings which refer to a DataContext of another control, etc.. I found helpful putting a TextBlock which Text property is bound to the same binding source in this way you can see what exactly bound since TextBlock will display a type name of a bound object.
For instance you have following failed binding:
<ItemsControl ItemsSource="{Binding Parent.DataContext.ActiveItem.DataContext}" />
<!-- See what is bound, if failed - try previous level -->
<TextBlock Text="{Binding Parent.DataContext}" />
<TextBlock Text="{Binding Parent.Inner.Items}" />
<TextBlock Text="{Binding Parent.Inner}" />
Useful links:
Debugging Data Bindings in a WPF or Silverlight Application
Nice trick using special DebugConverter which allows break a debugger whilst doing a binding, see Debugging WPF DataBinding article
I have been happily using the wonderful snippet from 'Switch on the Code' to detect and report binding errors since it was first published in 2009...
http://www.switchonthecode.com/tutorials/wpf-snippet-detecting-binding-errors
edit: still works excellently on VS2012 (Sept 2013)
Update 25 Jan 2016
The link appears broken, so I'll paste in the relevant snippets...
using System.Diagnostics;
using System.Text;
using System.Windows;
namespace SOTC_BindingErrorTracer
{
public class BindingErrorTraceListener : DefaultTraceListener
{ //http://www.switchonthecode.com/tutorials/wpf-snippet-detecting-binding-errors
private static BindingErrorTraceListener _Listener;
public static void SetTrace()
{ SetTrace(SourceLevels.Error, TraceOptions.None); }
public static void SetTrace(SourceLevels level, TraceOptions options)
{
if (_Listener == null)
{
_Listener = new BindingErrorTraceListener();
PresentationTraceSources.DataBindingSource.Listeners.Add(_Listener);
}
_Listener.TraceOutputOptions = options;
PresentationTraceSources.DataBindingSource.Switch.Level = level;
}
public static void CloseTrace()
{
if (_Listener == null)
{ return; }
_Listener.Flush();
_Listener.Close();
PresentationTraceSources.DataBindingSource.Listeners.Remove(_Listener);
_Listener = null;
}
private StringBuilder _Message = new StringBuilder();
private BindingErrorTraceListener()
{ }
public override void Write(string message)
{ _Message.Append(message); }
public override void WriteLine(string message)
{
_Message.Append(message);
var final = _Message.ToString();
_Message.Length = 0;
MessageBox.Show(final, "Binding Error", MessageBoxButton.OK,
MessageBoxImage.Error);
}
}
}
And to set it up/initialize it...
namespace WpfListeningForTraceErrors
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
BindingErrorTraceListener.SetTrace();
InitializeComponent();
}
}
}
You can add this to every control that binds
PresentationTraceSources.TraceLevel="High"
And run the program in debug, the detailed binding information will appear in your Output window. It may help a bit. You can also create a pass though converter to catch an error (catches the problem some times but not always). There are no good tools for debugging XAML in general that I am aware of.
You can download a tool called Snoop that will allow you to debug bindings. It provides a view of your WPF applications visual tree higlighting any binding errors that it finds.
You can get some basic information about binding errors in the Output Window in Visual Studio. It will show the binding expression path error and the line on which the error occured.
In VisualStudio goto Tools->Extentions and Updates->(download Output Enhancer). When you build your solution you will get the exact kind of error message you posted in Red color if there is a binding error.

WPF error message: Partial declaration must not specify different base classes

Why do I have this error message for a UserControl:
Partial declaration of
MyNamespace.MyUserControl must not
specify different base classes
Just because I inherited from another UserControl class I created in another namespace whereas this other namespace is referenced in the XAML as
xmlns:my="clr-namespace:ReferedNamespace;assembly=ReferedNamespace"
Little to go on here, but this usually happens when the code behind and the xaml file do not inherit from the same base class.
Since we do not have all the details concerning your problem,
I'll create a situation that will cause the same exception to be thrown,
this might help you understand your problem.
As an example, just create new WPF application using Visual Studio,
The XAML might look something like this:
<Window x:Class="WpfApplication1.MainWindow" .....>
The code behind would then contain something like this:
public partial class MainWindow : Window
{
//Code here
}
Note the 'partial' modifier here. It means this class (MainWindow) might
not be defined in a single file but spread out across multiple files,
in this case the XAML (.xaml.cs) and the CS (.cs) files.
Now add a new UserControl to the solution. It will be named UserControl1.
Without making any changes to the XAML, change the code behind for the MainWindow:
public partial class MainWindow : UserControl1
{
//Code here
}
Now you'll get the exception you questioned about.
Look for something like this in your code, if you still can't find a solution,
please provide more code.
look to both your .cs and .xaml files at this parts
in .xaml file :
<Window x:Class="BUSsAsDesign.GUI.IGPopUP" > ...... </Window>
in .cs file :
namespace BUSsAsDesign.GUI
{
public partial class IGPopUP : Window
{
//code here
}
}
Now if u wanna change Window to UserControl
change
<Window x:Class="BUSsAsDesign.GUI.IGPopUP" > ....... </Window>
<!--**becomes**-->
<UserControl x:Class="BUSsAsDesign.GUI.IGPopUP" > ....... </UserControl>
namespace BUSsAsDesign.GUI
{
public partial class IGPopUP : Window
{
//code here
}
}
//**becomes**
namespace BUSsAsDesign.GUI
{
public partial class IGPopUP : UserControl
{
//code here
}
}
- i hope it`s useful :) .
I wanted to add this piece of information. In Visual Studio 2017, There is a bug which I haven't had time to dig into with much depth, but it causes this error. (from the OP)
Overview: When declaring a partial class as an x:Class for a resource xaml file, it will cause this error, and after removing the declaration, the error will persist.
To reproduce this bug, (or if you are here because you are getting this error message)
Step 1: Create a new WPF Project.
Step 2: Create a new Resource File
Step 3: Change the resource files name-space to the projects main namespace (remove the bit at the end.)
Step 4: In the resource files declaration/header section, add an x:Class declaration specifying your MainWindow (default startup window object) as the Class for that resource file. (EG: x:Class=MainWindow)
Step 5: Clean/Rebuild Solution
Step 6: You should now be getting this error from the OP. So remove the x:Class Declaration from your header on the Resource File, and save/clean/rebuild the project.
If the bug was reproduced, the error should remain, even though you have removed the x:Class declaration from the resource file.
The only solution I could find for this bug, is to delete the projects Bin folder, and any other folder with builds in it.
After deleting them, Clean/Rebuild your project, and the error should be gone.

Programmatically triggering the HyperlinkButton navigation

I'm using the Silverlight 3 HyperlinkButton and I want to programmatically trigger the navigation that normally occurs when the button is clicked. There does not appear to be a public method that supports this.
The OnClick method is protected so I could inherit from this control to gain access to this method from a custom control but is there a better way to go about this?
Looking at the implementation of the OnClick method using Reflector does not give me an obvious hint for a better way and the complexity of the code makes me wonder if there is a good reason for not allowing this event to be triggered programmatically. The lowest level managed code call is to MS.Internal.XcpImports.NavigateToSafeURINative and I don't see any public method in the code path that I could use.
For an in browser application, the HtmlWindow.Navigate does the trick as follows, relying on a unique target name to make sure it opens in a different tab or window to the current window hosting the silverlight application.
var hostingWindow = HtmlPage.Window;
hostingWindow.Navigate(siteHyperLinkbutton.NavigateUri, siteHyperLinkbutton.TargetName);
For an out of browser application, the best solution I have found is to derive a very simple custom class from HyperlinkButton and implement a public method that in turn invokes the protected OnClick method as shown below. This custom class can be declared in XAML with the appropriate NavigateUri and TargetName properties, just like the base HyperlinkButton. I was hoping to avoid creating a custom class by invoking the OnClick method via reflection but this not possible due to the Silverlight Security Considerations for Reflection.
public class CustomHyperlinkButton : HyperlinkButton
{
/// <summary>
/// Exposes the base protected OnClick method as a public method.
/// </summary>
public void OnClickPublic()
{
OnClick();
}
}
You could link the button to a Command, then trigger the command anywhere from Code using Command.Execute(). Psuedo code:
XAML:
<UserControl x:Class="ClassName"
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:commands="clr-namespace:Microsoft.Practices.Composite.Presentation.Commands;assembly=Microsoft.Practices.Composite.Presentation">
<Button commands:Click.Command="{Binding MyCommand}" />
</UserControl>
CODE (behind or MVVM):
public class ClassName
{
///Class constructor
public ClassName()
{ /// implement the command behaviour as a delegate
MyCommand = new DelegateCommand<object>(
delegate{
/// do your OnClick() behaviour implementation here
}
);
}
private DelegateCommand<object> _myCommand;
public DelegateCommand<object> MyCommand
{
get { return _myCommand; }
set { myCommand=value;
OnPropertyChanged("MyCommand");}
}
/// Another method called from somewhere else in code
void SomeOtherMethod()
{
MyCommand.Execute(null);
}
}
This works particularly well in MVVM world.

Resources