StaticProperties in Resource Dictionary - xaml

My XAML has been working fine, referencing a Static Property of a static class
<TextBox IsReadOnly="{x:Static loc:StateMachine.IsReadOnly}" />
I now want to refactor the above, so I can use a ResourceDictionary
So, my resource dictionary is
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:stat="clr-namespace:MyProjectHelper"
>
<stat:StateMachine x:Key="StaticResources" />
</ResourceDictionary>
On my XAML, I removed the namespace reference called loc (which I was using) and I add a reference to the resource dictionary (which works since my views show and converters do their job) but when I add the following code
<TextBox IsReadOnly="{StaticResource StaticResources.IsReadOnly}" />
I get a runtime exception
'Provide value on 'System.Windows.StaticResourceExtension' threw an exception.' Line number '50' and line position '97'.
My research shows this is something wrong wit the XML - it could be a typo (checked) or an unexpected value but I can't see what I need to do to fix this despite looking over SO and Google
I also tried
<TextBox IsReadOnly="{Binding Source={StaticResource StaticResources}, Path=IsReadOnly}" />
but the exception is
'The invocation of the constructor on type 'SeoHelper.StateMachine' that matches the specified binding constraints threw an exception.' Line number '9' and line position '6'.

{StaticResource } binding needs to be able to instantiate your class, and it had problem to do so because the class was static. Your last trial would've worked if only the class wasn't declared as static.
Possible workaround if you need to keep your class static is, you can register the property instead of the class to resource dictionary using StaticExtension :
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:stat="clr-namespace:MyProjectHelper"
>
<x:StaticExtension Member="stat:StateMachine.IsReadOnly" x:Key="StaticResources"/>
</ResourceDictionary>
Then binding to the resource can be done as usual :
<TextBox IsReadOnly="{StaticResource StaticResources}" />

Related

XAML binding intellisense in a separate ContentView file used in a ListView

I have a ListView with this item template:
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<views:ProjectListEntry />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
ProjectListEntry is fairly complex and is used in another ListView, so I have it in its own file. I've set it up like this:
<ContentView
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
...
BindingContext="{x:Static vms:DesignTimeData.ProjectListEntryVm}">
As you can see, to get binding Intellisense (using ReSharper), I tried to set BindingContext to a static member on the DesignTimeData class. This works fine for my Pages (where I replace the BindingContext at runtime), but for ContentViews used in ListViews, the ContentView's BindingContext seems to be inherited (from the ViewCell, I guess). This means that the explicit BindingContext on my ContentView will actually override the BindingContext set on the ViewCell by the ListView, and all my list elements will reflect the static design-time data at runtime. But if I remove the BindingContext, I get no intellisense for the members I bind to inside the ContentView file.
Is there a simple way to get Intellisense for bindings in a ContentView like this?
(As mentioned, I can't inline the ContentView in the ListView definition, because the ContentView is fairly complex and used in several lists. I also can't use some kind of VM locator, because although I'm using bindings, I'm not using "full" MVVM - I'm using a Redux-like architecture instead. And I guess a VM locator wouldn't work for this case anyway for the same reasons the above doesn't work.)
(Cross-posted from the Xamarin Forums where I didn't get any reply.)
This solution seems to work fine. In short: Add
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
and use d:DataContext instead of BindingContext. Going from the example above, it should look like this:
<ContentView
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
...
BindingContext="{x:Static vms:DesignTimeData.ProjectListEntryVm}">
This leads to working binding intellisense from ReSharper and does not cause issues when run.

XAML Margin in resources

How do I define XAML margin in Windows universal app resources? I tried to define it as
<Thickness x:Key="MyMargin" Left="10" Top="20" Right="10" Bottom="20" />
by this does not compile, I get
XamlCompiler error WMC0100: XAML Thickness type cannot be constructed. In order to to be constructed in XAML, a type cannot be abstract, interface, nested, generic or a struct, and must have a public default constructor
The syntax for Windows XAML is as follows:
<Thickness x:Key="myMargin">10,20,10,20</Thickness>
which could be simplified to:
<Thickness x:Key="myMargin">10,20</Thickness>
I had it working by binding it to a String:
<x:String x:Key="MarginLeftPage" >120,0,0,0</x:String>
[...]
Grid Margin="{StaticResource MarginLeftPage}">

Binding Visibility to DataContext

I have a value converter that converts null to Visibility.Collapsed. Now I try to use it in a user control so that the whole control would collapse when it's DateContext is null
The control looks like this:
<UserControl x:Class="PhoneApp.Controls.Header"
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"
Visibility="{Binding Converter={StaticResource ToVisibility}}"
d:DesignHeight="150" d:DesignWidth="480"> <-- some body here -->
And it is used like this
<my:Header DataContext="{Binding SectionHeader}"/>
Where SectionHeader is a view model property.
I hava a similar control where I don't bind DataContext but some custom DP and the collapsing there works fine. However, in this one, the value converter seems to be called only when the SectionHeader != null. When it is null, the control is rendered with empty children.
I thought about not using DataContext here but the control is much cleaner with it.
Why binding to DataContext doesn't work? What do you suggest?
In this case, when DataContext is null, binding will use value specified in TargetNullValue property. So simply set TargetNullValue=Collapsed and you're good to go :
Visibility="{Binding TargetNullValue=Collapsed}"
Reference : [How to Set TargetNullValue to Visibility.Collapsed in Binding]

How to add a class to a xaml page

this is windows phone 8 app.
I have a class like this in namespace MyApp.Converters:
public class CustomConverter : IValueConverter
{
}
I want to add this to a XAML page, but I don't know how?!
I did this:
xmlns:MyApp.Converters="clr-namespace:MyApp.Converters"
and
<phone:PhoneApplicationPage.Resources>
<MyApp.Converters:CustomConverter x:Key="customConverter"/>
</phone:PhoneApplicationPage.Resources>
I get this error:
Length cannot be less than zero
How to add a class to a XAML page? thanks
we can have the following mapping to the namespace
<phone:PhoneApplicationPage xmlns:c="clr-namespace:MyApp.Converters">
<UserControl.Resources>
<c:CustomConverter x:Key="myconverter">
</c:CustomConverter>
</UserControl.Resources>
and you can bind the key as below wherever you need it
{Binding Converter={StaticResource myconverter}}
also you can refer to the following link which may help you
http://www.mindfiresolutions.com/Giving-alternate-color-to-each-row-of-ListBox-in-Windows-phone-7-2280.php
There seems to be an issue when you put a dot in the prefix name. If you remove it then it should work:
xmlns:MyAppConverters="clr-namespace:MyApp.Converters"
and
<phone:PhoneApplicationPage.Resources>
<MyAppConverters:CustomConverter x:Key="customConverter"/>
</phone:PhoneApplicationPage.Resources>

How to parse xaml file having custom class,to get the list of all objects?

I went through the tons of similar posts but nothing seems to work in my case. All I want to do is load a xaml file (located in some other assembly), and iterate through the different elements/objects to check for a certain attribute value.
I could have read it as a simple XML file, but things like styles etc cannot be caught through xml parsing.
After searching a lot,I tried the following two things:
I removed the x:Class=".." from the xaml
I also added the assembly=XBase.UI in this ( as my original xaml didn't have this and I read that when loading dynamically, you need to know specify the assembly)
then I loaded the remaining file as xml stream.
Then I called XamlReader.Load(stream)
This seems to work for people who posted queries, but I get exception
'System.Windows.Markup.XamlParseException : 'The invocation of the constructor on type 'XBase.UI.XControlBase' that matches the specified binding constraints threw an exception.' Line number '6' and line position '55'.
----> System.InvalidOperationException : The calling thread must be STA, because many UI components require this.'
The second thing I tried was to use the XamlReader.Parse and provide the ParserContext along with it.
This is what I did:
var context = new ParserContext();
context.XamlTypeMapper = new XamlTypeMapper(new string[] { });
context.XamlTypeMapper.AddMappingProcessingInstruction("UI", "XBase.UI", ""); //assemblyname is empty as my original file doesn't have one
context.XmlnsDictionary.Add("UI", "clr-namespace:XBase.UI;assembly=XBase.UI");
string text = File.ReadAllText(xamlfile);
var object = XamlReader.Parse(xamlfile, context);
This too throws an exception:
'System.Windows.Markup.XamlParseException : 'Cannot create unknown type '{clr-namespace:XBase.UI}XControlBase'.' Line number '1' and line position '2'.
----> System.Xaml.XamlObjectWriterException : 'Cannot create unknown type '{clr-namespace:XBase.UI}XControlBase'.' Line number '1' and line position '2'.'
My original xaml file
<UI:XControlBase x:Class="XBase.UI.XListView"
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:UI="clr-namespace:XBase.UI" Height="Auto" Width="Auto" IsTabStop="False"
mc:Ignorable="d"
Visibility="{Binding IsVisible, Converter={StaticResource VisibilityConverter}}">
<UI:XControlBase.Resources>
<UI:ButtonTemplateSelector x:Key="ButtonSelector" />
</UI:XControlBase.Resources>
<UI:ItemControlWrapper
ItemsSource="{Binding ButtonList}"
ItemTemplateSelector="{StaticResource ButtonSelector}"
IsTabStop="False">
<UI:ItemControlWrapper.ItemsPanel>
<ItemsPanelTemplate >
<StackPanel Orientation="{Binding ListOrientation}" />
</ItemsPanelTemplate>
</UI:ItemControlWrapper.ItemsPanel>
</UI:ItemControlWrapper>
</UI:XControlBase>
Please help me out here. I am not even sure if this is the right way to achieve what I want. If there is another way to list all of the elements of certain kind in a more meaningful way other than
the XmlDocument's GetElementsByTagName, please let me know.
Thanks in advance!