XmlnsDefinitionAttribute and ambiguous types - xaml

Let's assume I have the following attributes on my assembly:
[assembly: XmlnsDefinitionAttribute("urn:foo", "NS1")]
[assembly: XmlnsDefinitionAttribute("urn:foo", "NS2")]
Then let's assume I have a few classes in that assembly:
namespace NS1
{
public class Class1 {}
}
namespace NS1
{
public class Class2 {}
}
namespace NS2
{
// Here's the duplicate class name. OK in C#, but ambiguous in XAML
public class Class1 {}
}
Then let's assume that my XAML is like so:
<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:foo="urn:foo"
Title="MainWindow" Height="350" Width="525">
<ListBox>
<foo:Class2 />
<foo:Class1 /> <!-- XAML parser does not like this: Ambiguous type reference -->
</ListBox>
</Window>
Putting aside any design issues with having two or more classes named the same within an assembly, is there any way to provide the needed specificity without resorting to this?
<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:foo="urn:foo"
xmlns:foo2="clr-namespace:NS2;assembly=AssemblyName"
Title="MainWindow" Height="350" Width="525">
<ListBox>
<foo:Class2 />
<foo2:Class1 />
</ListBox>
</Window>
In some special XAML syntax? In an attribute I can put on NS2.Class1 (e.g. XamlClassName("NS2_Class1"))?

You could use:
[assembly: XmlnsDefinitionAttribute("urn:foo", "NS1")]
[assembly: XmlnsDefinitionAttribute("urn:foo", "NS2")]
[assembly: XmlnsDefinitionAttribute("urn:foo2", "NS2")]
and then:
xmlns:foo2="urn:foo2"
and finally:
<foo2:Class1 />
Regards,
H.Dolder

Related

How do I make a generic ContentPage that uses Type parameters?

If I need to post more code, then let me know, but I think what I have is sufficient to convey what I am trying to do. I can do it if I don't use XAML to define the page content, but when I try it with XAML, addng the <TViewModel,TDataModel> causes InitializeComponent() and any named elements in the XAML to get flagged as not found.
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class BaseSelectListPage<TViewModel,TDataModel> : ContentPage
where TViewModel : BaseSelectListViewModel<TDataModel>, new()
{
private TViewModel _viewModel { get; set; }
public BaseSelectListPopup()
{
_viewModel = new TViewModel();
BindingContext = _viewModel;
InitializeComponent(); // InitializeComponent gets flagged as not found
ExampleElement.Spacing = 5; // ExampleElement also gets flagged as not found
}
// rest of class
}
I don't know how to define the generic types in XAML, but here is what I tried.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="IRA.Views.SelectLists.BaseSelectListPage<TViewModel,TDataModel>">
<!-- this is obviously what I don't know how to do ^^^^ -->
<ContentPage.Content>
<StackLayout x:Name="ExampleElement">
<Label Text="Thanks for helping"/>
</StackLayout>
<!-- various elements -->
</ContentPage.Content>
</ContentPage>

DataBinding and Incomplete Microsoft Documentation

Basically, I'm working through the Microsoft tutorial on WPF:
https://learn.microsoft.com/en-us/dotnet/opbuildpdf/framework/wpf/data/toc.pdf?branch=live
I get to page 8, and (in my opinion) Microsoft screwed up. They don't give any C# code-behind that is necessary to run the following XAML:
<DockPanel
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:SDKSample">
<DockPanel.Resources>
<c:MyData x:Key="myDataSource"/>
</DockPanel.Resources>
<DockPanel.DataContext>
<Binding Source="{StaticResource myDataSource}"/>
</DockPanel.DataContext>
<Button Background="{Binding Path=ColorName}" Width="150" Height="30">
I am bound to be RED!</Button>
</DockPanel>
I follow their description as best as possible, but all I get is this following error message.
The name "MyData" does not exist in the namespace "clr-namespace:SDKSample".
I do what I'm supposed to do: create a c# file, using "Add New Item" and build it, but still that error code pops up again. To save people from having to look up the documentation, here's what they ask for:
Consider the following example, in which the binding source object is
a class named MyData that is defined in the SDKSample namespace. For
demonstration purposes, MyData class has a string property named
ColorName, of which the value is set to "Red". Thus, this example
generates a button with a red background.
I've looked in the various SDK's for this example, hoping I'd find the mysterious C# file somewhere, but alas I can't find it. It seems like Microsoft forgot a link. You know, even if it is somewhere in an SDK, it is extremely hard to find. As someone in a learning-mode, I'd hope that all the gritty details would be provided in the documentation, not just the quote from above, which doesn't go into any details as to where to put the C# file, how you are supposed to build so it will properly get registered as existing.
So, if anyone can find a nice description as to how to get the XAML code to work, by creating a C# class named "MyData" in a "SDKSamples" namespace, I'd be very appreciative.
the xaml works when you add the following:
namespace SDKSample
{
public class MyData
{
public Brush ColorName { get; set; } = Brushes.Red;
}
}
<Window x:Class="StackExchangeQuestion.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:StackExchangeQuestion"
mc:Ignorable="d"
xmlns:c="clr-namespace:SDKSample"
Title="MainWindow" Height="350" Width="525">
<DockPanel >
<DockPanel.Resources>
<c:MyData x:Key="myDataSource"/>
</DockPanel.Resources>
<DockPanel.DataContext>
<Binding Source="{StaticResource myDataSource}"/>
</DockPanel.DataContext>
<Button Background="{Binding Path=ColorName}" Width="150" Height="30">
I am bound to be RED!</Button>
</DockPanel>
</Window>
I'd like to add that Microsoft assumes that you have all the stuff between <Window x:Class and Width="525"> already there. It's kind of sloppy work to just leave out that massive detail in their documentation. Thanks to Milan for getting me to look at what should go inside the <Window>...</Window> part of the code.
Also, in the interest of completeness, the C# code:
using System.Windows;
using System.Windows.Media;
namespace StackExchangeQuestion
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}
namespace SDKSample
{
public class MyData
{
public Brush ColorName { get; set; } = Brushes.Red;
}
}

Using x:Static expression with ConverterParameter property

I've seen examples of the "x:Static" expression being used to specify the ConverterParameter property of a binding in WPF XAML. However, as far as I can tell, Xamarin will not allow you to set the property in this way. Specifying the ConverterParameter in the code behind works fine, using a StaticResource expression works fine, using a literal value, fine. Could someone please point me to an example of this being done in Xamarin?
My XAML:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="OMS.ProductionPickupPage"
xmlns:local="clr-namespace:OMS;assembly=OMS"
Title="Production Pickup"
Padding="5,5,5,5">
<ContentPage.Resources>
<ResourceDictionary>
<local:PickerIndexConverter x:Key="PickerConverter" />
</ResourceDictionary>
</ContentPage.Resources>
<!-- ... -->
<Picker x:Name="LoadingFacility_Picker" Title="Loading Facility" SelectedIndex="{Binding SelectedLoadingFacility, Mode=OneWayToSource,
Converter={StaticResource PickerConverter}, ConverterParameter={x:Static local:TestClass.TestMember}}" />
This is the exception thrown by the LoadFromXml method in InitializeComponent():
System.Exception: Property is not valid for this Expression
Stack Trace:
[External Code]
0xC in OMS.ProductionPickupPage.InitializeComponent at e:\Workspace\sumrallj\OMS\OMS\OMS\obj\Debug\ProductionPickupPage.xaml.g.cs:42,-1 C#
0x14 in OMS.ProductionPickupPage..ctor at e:\Workspace\sumrallj\OMS\OMS\OMS\ProductionPickupPage.xaml.cs:17,-1 C#
0x1 in OMS.App.GetMainPage at e:\Workspace\sumrallj\OMS\OMS\OMS\App.cs:14,-1 C#
0x22 in OMS.iOS.AppDelegate.FinishedLaunching at e:\Workspace\sumrallj\OMS\OMS\OMS.iOS\AppDelegate.cs:34,-1 C#
0xB in MonoTouch.UIKit.UIApplication.Main at /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:62,4 C#
0x3B in MonoTouch.UIKit.UIApplication.Main at /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:46,4 C#
0x8 in OMS.iOS.Application.Main at e:\Workspace\sumrallj\OMS\OMS\OMS.iOS\Main.cs:17,-1 C#
TestClass and TestMember are both static and I've also tried this with an enum.
namespace OMS
{
public static class TestClass
{
public static string TestMember = "Test";
}
}

Indexing collection properties with enums in XAML

While {Binding Path=CollectionProperty[2]} works fine, I can't get it working with an enum, i.e. {Binding Path=CollectionProperty[SomeEnum.Value2]}. What would be a proper syntax for that, if possible at all? Thanks.
Just specify the enum value as an unadorned string. E.g. given:
public enum Foo
{
Value1,
Value2
}
public class MainWindowVm
{
public string this[Foo foo]
{
get { return Enum.GetName(typeof(Foo), foo); }
}
}
Specify the enum value like so:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainWindowVm/>
</Window.DataContext>
<Grid>
<TextBlock Text="{Binding Path=[Value1]}"/>
</Grid>
</Window>
x:Static markup extension is not required because the XAML parser has built in support that will map the provided string to the values supported by the target enum.
Well, I tried binding to a property of type Dictionary<Foo, String> (where Foo is an enum) like this:
{Binding Foos[{x:Static my:Foo.Fizz}]}
... but that threw a binding exception at runtime.
Curiously, though, using an int as the indexer even for properties that are indexed on an enum seems to work. This:
{Binding Foos[2]}
... worked just fine. So if you're willing to represent your enum values as integers in XAML then you can do it that way.
Otherwise I think your best bet would be to bind directly to Foos through a value converter, passing {x:Static my:Foo.Bar} as the converter parameter.

XmlnsDefinitionAttribute combined with x:Name causes compilation error with code generation

I have and issue with using the XmlnsDefinition attribute within a silverlight 4 assembly.
Here's the test case:
In AssemblyInfo.cs of the silverlight project I add the following:
[assembly: XmlnsDefinition("urn:foo", "SilverlightApplication1")]
[assembly: XmlnsDefinition("urn:foo", "SilverlightApplication1.SomeNamespace")]
I edit MainPage.xaml.cs and to make it look like so:
namespace SilverlightApplication1
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
}
}
namespace SilverlightApplication1.SomeNamespace
{
public class SomeControl : ContentControl
{
}
}
Now in MainPage.xaml I have the following:
<UserControl x:Class="SilverlightApplication1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:foo="urn:foo">
<Grid>
<foo:SomeControl>
<TextBlock Text="Hello World"/>
</foo:SomeControl>
</Grid>
</UserControl>
This compiles and runs fine. The problem occurs when I add the x:Name attribute to the SomeControl tag.
This does not compile:
<foo:SomeControl x:Name="bar">
<TextBlock Text="Hello World"/>
</foo:SomeControl>
Looking at the .g.i.cs file that gets generated, the control is declared as
internal SomeControl bar;
The file is missing either the using statement or the full type name. I've also tried this in WPF and the results are the same. Can anyone tell me what, if anything, I'm doing wrong?
I have the same issue. Based on my searching, it looks like this is not currently supported.
http://forums.silverlight.net/forums/t/84877.aspx
http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/7e7a032a-dad3-4e02-9e5a-d73e346b75ed/