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";
}
}
Related
I am developing a chat application in Xamarin Forms and I am trying to add conditional formatting depending on whether it is an incoming or outgoing message.
This is my XAML:
<Frame
Margin="1"
Padding="0"
x:Name="FrameRef"
x:DataType="model:ChatMessage">
<Frame
CornerRadius="10"
Padding="7"
BackgroundColor="LightBlue"
HasShadow="false"
Margin="10,10,80,0">
<Frame.Triggers>
<DataTrigger
TargetType="Frame"
Binding="{Binding Source={x:Reference FrameRef}, Path=x:DataType.From}" Value="+1456456456">
<Setter Property="BackgroundColor" Value="Yellow"/>
</DataTrigger>
</Frame.Triggers>
When I use Path="Margin" and Value="1" it works.
I am now trying to make it work with the Path being x:DataType="model:ChatMessage" and checking the 'from'-field (indicating if the message was incoming or outgoing).
I'm not sure the Data Trigger is quite right for this application, since you're really depending on a data type and not really the content per se of another field. From the documentation:
The DataTrigger class is suitable for checking values on other controls, as well as any property on the control to which it has been added.
What you probably want instead is a Value Converter that handles locating a StaticResource and applying a style for you based on the message type. Full Microsoft Documentation here.
On your XAML element, you'd do something like this:
<Frame Style="{Binding foo, Converter={StaticResource FooToStyleConverter}}"/>
Your converter would work something like this:
public class FooToStyleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var someValue = (DataTye)value; // Convert 'object' to whatever type you are expecting
// evaluate the converted value
if (someValue.From != null && someValue.From == Enum.SomeoneElse)
return (Style)App.Current.Resources["StyleReceived"]; // return the desired style indicating the message is from someone else
return (Style)App.Current.Resources["StyleSent"]; // return a style indicating the message is from the sender
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
// Usually unused, but inverse the above logic if needed
throw new NotImplementedException();
}
}
Lastly, set up your converter as a Static Resource in App.xaml (or as a local resource on the page) so your page can properly reference it
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DataBindingDemos">
<ContentPage.Resources>
<ResourceDictionary>
<local:FooToStyleConverter x:Key="FooToStyleConverter" />
....
Can you please help me translate this Xamarin xaml into c#?
BackgroundColor="{Binding IconColor, Converter={StaticResource LocalHexColorFromStringConverter}}"/>
Thanks!
You can translate it by MyBtn.SetBinding(Button.BackgroundColorProperty, "IconColor", BindingMode.OneTime, new LocalHexColorFromStringConverter()) ;
I make a test with Button's background color.
Button MyBtn = new Button();
MyBtn.Text = "test";
MyBtn.SetBinding(Button.BackgroundColorProperty, "IconColor", BindingMode.OneTime, new LocalHexColorFromStringConverter()) ;
Content = MyBtn;
Here is LocalHexColorFromStringConverter.cs
public class LocalHexColorFromStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return Color.FromHex((string)value);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value;
}
}
Can I ask what the difference is between "new LocalHexColorFromStringConverter()" and "converter: LocalHexColorFromStringConverter()" ?
Do you mean "new LocalHexColorFromStringConverter()" and "converter: LocalHexColorFromStringConverter"?
If so, they are same, converter: LocalHexColorFromStringConverter is wirte type in Xaml , converter: is prefix, it explains the specific path of this class, If you want to call it from any pages, you need to write it in the App.xaml.
For example, you add add it in the App.xaml.
<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:converters="clr-namespace:OAuthGoogleDemo"
x:Class="OAuthGoogleDemo.App">
<Application.Resources>
<ResourceDictionary>
<converters:LocalHexColorFromStringConverter x:Key="HexColorFromStringConverter" />
</ResourceDictionary>
</Application.Resources>
</Application>
Then use it in the Mainpage.xaml with Converter={StaticResource HexColorFromStringConverter}}"
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>
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/
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