Silverlight 4: "Invalid XAML" using Converter in DataTemplate - silverlight

maybe you could help me understand why I get an unhandled exception "Invalid XAML" in Visual Studio 2010 designer when trying to do the following on a Page.
I have a Converter named DateTimeConverter that converts a date into a German date string. The converter works fine. I've included the namespace and added the following to the page's resources:
<navigation:Page.Resources>
<myClasses:DateTimeConverter x:Key="dateTime" />
</navigation:Page.Resources>
Now I have a list box that I want to bind to a list of objects. I do the binding in code, but I would like to define the data template. Thus I've added the following to my layout:
<ListBox x:Name="lbConversation" BorderBrush="#00000000">
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderThickness="0" Padding="4">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Message, Mode=OneWay}" />
<TextBlock Text="{Binding TimeStamp, Mode=OneWay, Converter={StaticResource dateTime}}" />
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And this works fine when I run. However, in the code section, the code for the data template is undercurled and the designer says "Invalid XAML". When I remove the Converter=... part, this error is gone.
Is this a designer bug? What can I do?
EDIT
By the way: The exact same code does not throw the error within a WPF project!

Just adding to this question as I found a solution.
The solution to my case was here: http://forums.silverlight.net/post/618518.aspx
Apparently you must not have a space character in your project name or assembly name. D'oh!
Hope it helps.

Sorry, can't replicate this at all, do you have some design-time data that may be the cause of the weird error?
Also, since you said that you're using the converter to output german dates... wouldn't it be easier to let the framework do this kind of things, as it probably does them a lot better? Set the entire application thread's CultureInfo to german and all formatting will be done with that culture's settings; of course it's still possible you only want some controls internationalized...

I can't see anything wrong with your Xaml however I wonder if this is a result of the language setting used when the Xaml is parsed. By default Xaml is parsed using the InvariantCulture however it would appear that the designer in visual studio parses the Xaml using the current culture. Hence at times you can get unexpected differences in behaviour at design time than you do at runtime.
In fact if you do this in the constructor of your UserControl before calling InitializeComponent:-
this.Language = XmlLanguage.GetLanguage(Thread.CurrentThread.CurrentCulture.Name);
You might not need your converter at all.

I came across "Invalid XAML" error when I had my converter marked internal. Change the modifier to public and everything is as expected.
Hope this help.

Related

Binding DataContext in XAML With DataContext Set In Code

I have the following code:
ProcessMainWindow.xaml.cs
public ProcessMainWindow(SourceTableRowInfo rowContent)
{
InitializeComponent();
this.DataContext = rowContent;
}
ProcessMainWindow.xaml
<!--Insert Code---->
<TabItem x:Name="postProcessTab" Header="Post-Processes">
<local:PostProcessUserControl PostProcessItem="{Binding PostProcess, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</TabItem>
So RowContent has an element called PostProcess in it. I am trying to bind that element to a UserControl Dependency Property, but cannot get the binding to work. Based off what I was reading here (Using the DataContext) my understanding is that what I have should work, but I can't get it to work. So am I misunderstanding what it is saying? I have read a few other pages but still can't figure it out.
I have also tried:
<!--Insert Code---->
<TabItem x:Name="postProcessTab" Header="Post-Processes">
<local:PostProcessUserControl PostProcessItem="{Binding, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Path=PreProcess}" />
</TabItem>
If these are correct, I guess I have an error elsewhere in my code. I have yet to fully understand data binding in WPF to know if that is the case though so any help would be appreciated.
One thing to try is to put a trace on the Binding:
PostProcessItem="{Binding PostProcess, PresentationTraceSources.TraceLevel=High}.
Then look for what it tells you at runtime in the Output pane in VS. This can help you identify cases where your DataContext isn't what you think it is, or your Path is misspelled -- all the simple stuff that the compiler catches in C# but can't be detected at compile time in a late-binding/duck-typed miasma like XAML.
Don't leave those traces on bindings once you're done with them; they can really slow things down. Or at least set TraceLevel=None, to save trouble if think you'll be coming back to one later.

Is there any free Visual Studio plug-in/extension or external program to visualize XAML DataTemplate?

Visual Studio (10) gives the expected message "Intentionally Left Blank" in the designer.
I know already that I can do this with Blend, just looking around if there is an alternative solution...
I don’t really mind to graphically edit the template; I want only to see it without having to run the application.
Thanks!
Not exactly what you might want, but you can use XamlPad and just paste the content of your datatemplate into it. As long as you don't have layout related bindings, it should work well. Bindings are just ignored by xamlpad, and you need to add the 2 wpf namespace aliases by hand.
for example:
<TextBlock xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Text="{Binding test}"
Background="Red"
Width="20" Height="20"/>
the textblock is empty in XamlPad, but everything else works as expected.

Cross DomainDataSource Combobox SelectedItem Binding

I'm fairly new to Data binding & XAML, so this probably is fairly simple thing but I've been stumped on it for days now (and frustrated with more googling than i can track at this point) and would appreciate any pointers in the right direction. My only preference is to keep it in pure XAML if possible.
In my RIA SL4 project, I have two Entities PackageOS and OS where PackageOS has an association to OS through PackageOS.OS (associating through PackageOS.OSID <-> OS.ID - and [Include] + .Include() setup properly on relevant sections)
This is the template (defined in Page.Resource section along with all other involved DDS) I'm using in DataForm to get OSEntities List to bind into PackageOS Entity (coming from RIA GetOSEntities() using DDS):
<DataTemplate x:Key="POSItemTemplate">
<StackPanel>
<toolkit:DataField Label="PackageOS.OS">
<TextBlock Text="{Binding Source={StaticResource packageOSEntityDomainDataSource}, Path=Data.CurrentItem.OS}" />
</toolkit:DataField>
<toolkit:DataField Label="OS">
<ComboBox ItemsSource="{Binding Path=Data, Source={StaticResource osEntityDomainDataSource}}"
SelectedItem="{Binding Path=Data.CurrentItem.OS, Source={StaticResource packageOSEntityDomainDataSource}}"/>
</toolkit:DataField>
</StackPanel>
</DataTemplate>
The core problem is SelectedItem of ComboBox is not working. All the bindings are reachable from IDE Binding wizard so it's not a problem of me typing incorrect path. I can see packageOSEntityDomainDataSource.Data.CurrentItem to be of type PackageOS.
If i create a manual entry in backend database, the result is shown in PackageOS.OS textblock so I know it is properly being returned but SelectedItem refuses to pick it up (it ends up selecting the first value in dropdown list regardless of OS item in PackageOS).
Many thanks in advance!
Finally figured this out. Leaving my answer in hopes that it saves somebody else the time that I spent on this.
First Lesson
The problem was in the fact that I didn't have a custom Equality implementation for generated entities and default reference equality didn't work as I was using two different instances. Once I implemented IEquatable on my generated entities (through .shared.cs partial classes on server side) everything started working like a charm.
For details please see Silverlight ComboBox Control Population by Manishdalal
Second lesson
Do not use multiple DDS controls if you can help it. Especially once you use a write operation on a DDS, you cannot load/refresh any other DDS that is sharing the DomainContext until changes are committed. The link above shows how to avoid multiple DDS by using list generators when all you want is to pick up list of entities to fill ComboBox up.
My new code looks like this:
<DataTemplate x:Key="POSItemTemplate">
<StackPanel d:DataContext="{Binding Source=packageOSDomainDataSource, Path=Data.CurrentItem}">
<toolkit:DataField Label="OS">
<ComboBox DisplayMemberPath="Name"
ItemsSource="{Binding Path=OSList, Source={StaticResource OSListGenerator}}"
SelectedItem="{Binding Path=OS, Mode=TwoWay}" />
</toolkit:DataField>
</StackPanel>
</DataTemplate>
Where OSListGenerator is returning an IEnumerable<OSEntity> through its OSList property after loading it from DomainContext
Third Lesson
In DDS DataTemplate you have to be explicit with TwoWay Binding. This is the new behaviour; something that took me days to figure as most of the tutorials I referred to were using SL3 and I didn't realize that this was a breaking change in DDS DataTemplate behaviour in SL4.

Binding to images

I'm using a listbox with a template like the following.
<ListBox.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}" Width="100" />
</DataTemplate>
</ListBox.ItemTemplate>
I bind this to an observable collection conataining 130 paths to images (all do exist, read out using System.IO.Directory) but only a few get really displayed. No exceptions that come up. Only white places where the images should be. Has anybody seen something else.
Sascha
Never seen this before but Binding is suppressing errors by default. When there are errors you can see them when you run in debug en watch in the output window of visual studio and make sure the option of the combobox "Show output from:" is set to "Debug"
Hope that this will help you to the real problem.
EDITED:
If you don't see a problem may you can find it out by hooking into the Image.ImageFailed Event. More help can be found here :
http://msdn.microsoft.com/en-us/library/system.windows.controls.image.imagefailed%28v=VS.95%29.aspx

WPF XAML Bindings and CurrentCulture Display

I'm seeing some invalid behavior from XAML documents when the CurrentCulture is changed. When I have some elements like this in a Window:
<Window x:Class="WpfLocalizationLocBaml.Test"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:glob="clr-namespace:System.Globalization;assembly=mscorlib"
x:Name="wndTest"
Title="Test" Height="300" Width="300">
<StackPanel>
<TextBlock x:Name="lblCultureName"
Text="{Binding Source={x:Static glob:CultureInfo.CurrentCulture},
Path=DisplayName}" />
<TextBlock x:Name="lblLocaleDateValue"
Text="{Binding ElementName=wndTest, Path=TestDate}"/>
<TextBlock x:Name="lblLocaleNumberValue"
Text="{Binding ElementName=wndTest,Path=NumberValue,StringFormat=c}" />
</StackPanel>
</Window>
as well as a MessageBox.Show( NumberValue.ToString("c") ); when the form starts I'm seeing different results.
If I run the form with the default language all is well obviously. However, if I change the culture in code or at startup the bindings to the date and number values still show en-US formatting. The MessageBox.Show() value displayed appropriately reflects the current culture.
Question: Does WPF not respect CurrentCulture in bindings? And if so what exactly determines the culture that is used for the bindings. It's clearly en-US in my case, but regardless what I set in my project as the default language it always binds in en-US.
Any ideas appreciated...
It turns out that WPF does not respect the CurrentCulture by default in bindings, and instead defaults to xml:Lang setting defined in the XAML document or en-US if not provided. This is rather lame behavior - not sure why you would NOT have automatic culture formatting applied as every other UI technology, but...
Luckily there's an easy workaround that can be applied in the document's constructor or a Window/UserControl base class:
// MAKE SURE you set the language of the page explicitly or else
// all number and date formatting occurs using
this.Language = XmlLanguage.GetLanguage(
CultureInfo.CurrentCulture.IetfLanguageTag);
There's more information available in this blog post:
http://www.west-wind.com/weblog/posts/796725.aspx
It's also worth pointing out that the same thing happens in Silverlight, with the same solution except for swapping IetfLanguageTag for Name.

Resources