How to bind ResourceDictionary to ViewModelProperty - mvvm

I have ViewModel for MainWindow with property UriResource. How can I bind this property to ResourceDictionary? I have tried this code:
<Window.Resources>
<ResourceDictionary Source="{Binding UriResource}">
</ResourceDictionary>
</Window.Resources>
but I get error: All objects added to an IDictionary must have a Key attribute or some other type of key associated with them.

This is how my app.settings look like:
<Application x:Class="PcgTools.App"
...
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="....." />
</ResourceDictionary.MergedDictionaries>
<local:EnumToBooleanConverter x:Key="EnumToBooleanConverter"/>
<BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
<res:Strings
x:Key="LocStrings"/>
</ResourceDictionary>
</Application.Resources>
</Application>
Probably you need to add x:Key="....."

Related

TabbedPage renders multiple times in Xamarin Forms using shell

I have a problem using TabbedPages in my Xamarin.Forms mobile app (Shell).
When I navigate to a TabbedPage containing 3 tabs, the 3 tabs are crunched up and repeating themselves all down the page.
To replicate it I:
Created a standard Xamarin Forms Shell app in Visual Studio 2019 Version 16.4.5
Upgraded to Xamarin Forms 4.4.0.991640
Added a TabbedPage and changed the navigation of the About button to navigate to the TabbedPage instead.
Here is a photo of how it looks on my android phone
If I remember correctly it also happened when I deployed to my iPhone.
Update due to Jason's comment
All the code is automatically generated by Microsoft, my only interaction was to add an empty TabbedPage and change a line of code in AppShell.xaml.
(Note - while not relevant to this particular demo, I also got the same issue when navigating from a ListView in a ContentPage in my Xamarin.Forms app.)
Added TabbedPage1.xaml:
<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage 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="App1.Views.TabbedPage1">
<!--Pages can be added as references or inline-->
<ContentPage Title="Tab 1" />
<ContentPage Title="Tab 2" />
<ContentPage Title="Tab 3" />
</TabbedPage>
Added TabbedPage1.xaml.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace App1.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class TabbedPage1 : TabbedPage
{
public TabbedPage1()
{
InitializeComponent();
}
}
}
Amended AppShell.xaml (all I did was change the line from DataTemplate local:AboutPage to DataTemplate local:TabbedPage1):
<?xml version="1.0" encoding="UTF-8"?>
<Shell 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"
xmlns:local="clr-namespace:App1.Views"
Title="App1"
x:Class="App1.AppShell">
<!--
Styles and Resources
-->
<Shell.Resources>
<ResourceDictionary>
<Color x:Key="NavigationPrimary">#2196F3</Color>
<Style x:Key="BaseStyle" TargetType="Element">
<Setter Property="Shell.BackgroundColor" Value="{StaticResource NavigationPrimary}" />
<Setter Property="Shell.ForegroundColor" Value="White" />
<Setter Property="Shell.TitleColor" Value="White" />
<Setter Property="Shell.DisabledColor" Value="#B4FFFFFF" />
<Setter Property="Shell.UnselectedColor" Value="#95FFFFFF" />
<Setter Property="Shell.TabBarBackgroundColor" Value="{StaticResource NavigationPrimary}" />
<Setter Property="Shell.TabBarForegroundColor" Value="White"/>
<Setter Property="Shell.TabBarUnselectedColor" Value="#95FFFFFF"/>
<Setter Property="Shell.TabBarTitleColor" Value="White"/>
</Style>
<Style TargetType="TabBar" BasedOn="{StaticResource BaseStyle}" />
</ResourceDictionary>
</Shell.Resources>
<!-- Your Pages -->
<TabBar>
<Tab Title="Browse" Icon="tab_feed.png">
<ShellContent ContentTemplate="{DataTemplate local:ItemsPage}" />
</Tab>
<Tab Title="About" Icon="tab_about.png">
<ShellContent ContentTemplate="{DataTemplate local:TabbedPage1}" />
</Tab>
</TabBar>
<!-- Optional Templates
// These may be provided inline as below or as separate classes.
// This header appears at the top of the Flyout.
<Shell.FlyoutHeaderTemplate>
<DataTemplate>
<Grid>ContentHere</Grid>
</DataTemplate>
</Shell.FlyoutHeaderTemplate>
// ItemTemplate is for ShellItems as displayed in a Flyout
<Shell.ItemTemplate>
<DataTemplate>
<ContentView>
Bindable Properties: Title, Icon
</ContentView>
</DataTemplate>
</Shell.ItemTemplate>
// MenuItemTemplate is for MenuItems as displayed in a Flyout
<Shell.MenuItemTemplate>
<DataTemplate>
<ContentView>
Bindable Properties: Text, Icon
</ContentView>
</DataTemplate>
</Shell.MenuItemTemplate>
-->
</Shell>

How to reference converter in a ResourceDictionary file

I'm trying to create a resource dictionary file and reference a Value Converter. How can this be done?
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:converters="clr-namespace:CS.Runtime.Crew.Converters"
x:Class="CS.Runtime.Crew.Resources.CrewResourceDictionary" >
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<!--<converters:DateTimeToNullableDateTimeConverter x:Key="DateTimeToNullableDateTimeConverter" />-->
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
<DataTemplate x:Key="workGroupAttributesTemplate">
<Grid>
<controls:ExtendedDatePicker NullableDate="{Binding Attributes[DueDate], Converter={StaticResource DateTimeToNullableDateTimeConverter}}" Grid.Column="1" Grid.Row="4" />
</Grid>
</DataTemplate>
</ResourceDictionary>
First you add the class namespace
We assume class is Checker and checker is the namespace
Header
xmlns:checker="clr-namespace:Something.Checker;assembly=Something
Body
<checker:MySpecialValueConverter x:Key="MySpecialValue"/>
You can read more here
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/data-binding/converters#the-ivalueconverter-interface

Cannot filter by string from remote url

Created a WCF Data Service to pull data from Oracle database and when debugging in VS I can use the ?$filter syntax to filter returned sets.
However, using the remote url I cannot.
Point to note: I can filter by integers and dates, however I cannot filter by strings.
Also, I cannot filter by any string field in code. The filter is ignored.
Sample item below:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<feed xml:base="http://localhost:61905/CampaignerSVC.svc/" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://www.w3.org/2005/Atom">
<title type="text">Contacts</title>
<id>http://localhost:61905/CampaignerSVC.svc/Contacts</id>
<updated>2015-04-29T15:06:48Z</updated>
<link rel="self" title="Contacts" href="Contacts" />
<entry>
<id>http://localhost:61905/CampaignerSVC.svc/Contacts(23517014)</id>
<title type="text"></title>
<updated>2015-04-29T15:06:48Z</updated>
<author>
<name />
</author>
<link rel="edit" title="ContactList" href="Contacts(23517014)" />
<category term="Campaigner_DAL_WCF.ContactList" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
<content type="application/xml">
<m:properties>
<d:LicenseNumber m:type="Edm.Int32">23517014</d:LicenseNumber>
<d:ClientCode>2000</d:ClientCode>
<d:ClientName>Doodler</d:ClientName>
<d:ClientMnemonic>DD</d:ClientMnemonic>
<d:LastName>Kerr</d:LastName>
<d:FirstName>Rover</d:FirstName>
<d:MiddleName>Frank</d:MiddleName>
<d:Title>Mr.</d:Title>
<d:PreferredFirstName>Rover</d:PreferredFirstName>
<d:PreferredMiddleName>Frank</d:PreferredMiddleName>
<d:CompanyName m:null="true" />
<d:JobTitle m:null="true" />
<d:Gender>M</d:Gender>
<d:DateOfBirth m:type="Edm.DateTime">1947-04-27T00:00:00</d:DateOfBirth>
<d:PrimaryChapterCode m:type="Edm.Int16">400</d:PrimaryChapterCode>
<d:AlternateChapterCode m:type="Edm.Int16" m:null="true" />
<d:MainAddrStreetNo>121</d:MainAddrStreetNo>
<d:MainAddrLine1>So Crescent</d:MainAddrLine1>
<d:MainAddrLine2 m:null="true" />
<d:MainAddrLine3 m:null="true" />
<d:MainAddrCity>MAICK</d:MainAddrCity>
<d:MainAddrProvCode>ON</d:MainAddrProvCode>
<d:MainAddrProv>Ontario</d:MainAddrProv>
<d:MainAddrPostalCode>KB7</d:MainAddrPostalCode>
<d:MainAddrCountryCode>CA</d:MainAddrCountryCode>
<d:MainAddrCountry>Canada</d:MainAddrCountry>
<d:MainPhoneNum>610-000-0703</d:MainPhoneNum>
<d:MainPhoneExt m:null="true" />
<d:MainFaxNum m:null="true" />
<d:MainEmailAddr>someone#rogers.com</d:MainEmailAddr>
<d:CellPhoneNum m:null="true" />
<d:ChangeType>D</d:ChangeType>
<d:EventTimeStamp m:type="Edm.DateTime">2015-04-29T02:40:02</d:EventTimeStamp>
<d:PrivacyIndicator>N</d:PrivacyIndicator>
</m:properties>
</content>
</entry>
</feed>
You can filter by string also by using the string in quotes like below-
'string'
Ok, so the issue was that I had created a class to store the results from the entity model.
Although I had a DataKey value specified, the problem was that the field I specified was not unique, therefore the filters were being ignore (or only the first matching record was filtered).
What I had to do was decorate the class with a composite DataKey.

Own DataTemplateSelector MVVM

I'm using a MVVM-Pattern with a ModelView-First approach. This works fine, so far.
Now I have a UserControl (View) which should display various content depending on a Property located in my ViewModel.
First, I tried to solve the issue with DataTemplates and a DataTemplateSelector (See this tutorial) This was working very well. But I was not happy with the solution, because then I have a class (the overrided DataTemplateSelector) which is not connected to the ViewModel and can't be filled from the model.
So I tried to create a own TemplateSelector which uses a Property from the ViewModel. Unfortunately the DataTrigger is not triggering. The Binding from a CheckBox to the ViewModel is also working but not at the DataTrigger (even the designer can't find this path).
Ok, please have a look at the code:
<UserControl.Resources>
<!--Define Template which is displayed for Users-->
<DataTemplate x:Key="templateUser">
<Image
Name="logo"
Source="blanked out"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</DataTemplate>
<!--Define Template which is displayed for Administrators-->
<DataTemplate x:Key="templateAdmin">
<TextBlock Background="Yellow" Margin="3" Text="YEAH, I'm an Administrator" />
</DataTemplate>
<!--My own TemplateSelectpr-->
<DataTemplate x:Key="myTemplateSelector">
<ContentControl x:Name="DynamicContent" ContentTemplate="{StaticResource templateUser}"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsAdministrator}" Value="true">
<Setter TargetName="DynamicContent" Property="ContentTemplate" Value="{StaticResource templateAdmin}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</UserControl.Resources>
<Grid>
<ContentPresenter ContentTemplate="{StaticResource myTemplateSelector}"/>
</Grid>
Of course, I can seperate the Task in two further contentcontrols, but I don't want to maintain those if same content is intersecting.
So can someone suggest anything?
Best regards, and thanks in advance!
The simpler, the better: use a single template, which includes all the controls you need to show. Then switch their visibility using a binding to your property:
<UserControl.Resources>
<DataTemplate x:Key="myTemplate">
<Grid>
<Grid Visibility="{Binding IsAdministrator, Converter={StaticResource BooleanToVisibilityConverter}}">
<!-- Content for admin -->
</Grid>
<Grid Visibility="{Binding IsAdministrator, Converter={StaticResource NotBooleanToVisibilityConverter}}">
<!-- Content for user -->
</Grid>
</Grid>
</DataTemplate>
</UserControl.Resources>
<Grid>
<ContentPresenter ContentTemplate="{StaticResource myTemplate}"/>
</Grid>
Answer is to long for comment
Arnaud Weil brought me on the right way:
To access the Property 'IsAdministrator' in ViewModel from the Datatemplate, I gave the UserControl a Name e.g.:
<UserControl
x:Class="blanked out"
x:Name="this"
Used the code from Arnaud with some modifications, to inherit the Binding to the ViewModel from UserControl
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<helper:NotBooleanToVisibilityConverter x:Key="NotBooleanToVisibilityConverter"/>
<DataTemplate x:Key="myTemplate">
<Grid>
<Grid Visibility="{Binding DataContext.IsAdministrator, ElementName=this, Converter={StaticResource BooleanToVisibilityConverter}}">
<!-- Content for admin -->
<TextBlock Background="Yellow" Margin="3" Text="ICH BIN ADMNIN; JUCHUUU" />
</Grid>
<Grid Visibility="{Binding DataContext.IsAdministrator, ElementName=this, Converter={StaticResource NotBooleanToVisibilityConverter}}">
<!-- Content for user -->
<Image
Name="logo"
Source="/blanked out"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
</Grid>
</DataTemplate>
</UserControl.Resources>
And for the inverted BooleanToVisibilityConverter:
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace blankedout.Helper
{
[ValueConversion(typeof(bool), typeof(Visibility))]
public class NotBooleanToVisibilityConverter:IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var boolValue = (bool)value;
return !boolValue ? Visibility.Visible : Visibility.Hidden;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
Thanks once again to Arnaud Weil
Regards

UWP Semantic Zoom, ListView, VisualState

<SemanticZoom x:Name="Zoom" >
<SemanticZoom.ZoomedInView>
<ListView Name="HotelInList"
IsItemClickEnabled="False"
Style="{StaticResource HotelListViewStyle}"
ItemContainerStyle="{StaticResource HotelListItemContainerStyle}"
ItemsSource="{Binding Source={StaticResource HotelViewSource}}"
ItemTemplate="{StaticResource HotelListItemTemplate}"
SelectedItem="{Binding Selected, Mode=TwoWay}" >
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="ItemClick">
<Core:GoToStateAction StateName="DetailVisualState" />
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
<ListView.GroupStyle>
The interactivity snippet above doesn't work. It will complain about how HotelInList doesn't contain a visual state named DetailVisualState, which is left out for brevity for now, but it is a visualstate above part of the rootlayout grid
Would nesting inside the SemanticZoom block the EventTriggerBehavior?
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="ItemClick">
<Core:GoToStateAction StateName="DetailVisualState" TargetObject="{Binding ElementName=ThisPage}" />
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
Where ThisPage is the x:Name of the actual page, which forces the interaction to look down the resource tree and find from the the available resources the visualstate you requested.