Unity: Dependency Injection - unity-container

public partial class HTCmds : ResourceDictionary
{
private ICanvasService mCanvasService;
[Dependency]
public ICanvasService CanvasService
{
get { return mCanvasService; }
set { mCanvasService = value; }
}
public HTCmds()
{
CopyCommand = new DelegateCommand<object>(this.Copy, this.CanCopy);
ExitCommand = new DelegateCommand<object>(this.Exit);
}
public DelegateCommand<object> CopyCommand { get; private set; }
public DelegateCommand<object> ExitCommand { get; private set; }
}
Resource Dictionary Xaml:
<ResourceDictionary x:Class="HTCmds"
x:ClassModifier="public"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:commands="clr-namespace:Commands;assembly=UIInfrastructure"
xmlns:r="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"
xmlns:local="clr-namespace:Commands.Commands">
<local:HTCmds x:Key="thisobj"/>
<commands:CommandReference x:Key="CopyCommandReference" Command="{Binding Source={StaticResource thisobj}, Path=CopyCommand}"/>
<commands:CommandReference x:Key="ExitCommandReference" Command="{Binding Source={StaticResource thisobj}, Path=ExitCommand}"/>
</ResourceDictionary>
I've registered the ICanvasService but it's not getting injected in this class. Resource Dictionary is merged in the xaml file of a windows class:
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Commands/HTCmds.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Is there something specific with ResourceDictionary class?
Thanks & Regards,
Vishal.

Your HTCmds object is created by WPF by this line of XAML:
<local:HTCmds x:Key="thisobj"/>
WPF has no knowledge of Unity so it does not know how to resolve the dependencies using Unity. You need to resolve objects using UnityContainer.Resolve. You can't rely on WPF to do this for you.

Related

xamarin.forms: Changing language at runtim doesnt affect UI Hi

I am having an app where the user picks his or her language:
I have two resources files, both of which work because I can see the text showing up in Xaml.
A short overview:
Eng Resource:
<data name="Next" xml:space="preserve">
<value>next</value>
</data>
<data name="German" xml:space="preserve">
<value>German</value>
</data>
<data name="Arabic" xml:space="preserve">
<value>Arabic</value>
</data>
The Labels:
<Label Text="{x:Static resources:AppResources.German}"
VerticalOptions="Center"
Grid.Row="0"/>
<Label Text="{x:Static resources:AppResources.Arabic}"
VerticalOptions="Center"
Grid.Row="1"/>
<Label Text="{x:Static resources:AppResources.English}"
VerticalOptions="Center"
Grid.Row="2"/>
I know that they work, becaause when I change from one emulator to another (one in germany, one in england) the language changes automatically.
But I want the user to be able to change the language upon button click.
I tried:
case "english":
CultureInfo culture = new CultureInfo("en-US");
CultureInfo.DefaultThreadCurrentCulture = culture;
mainPage.FlowDirection = FlowDirection.LeftToRight;
break;
But the phone simply ignores the language change.
Any ideas why?
You can create a LocalizationResourceManager class that handles language changes and also will have a property with the translation. When the language changes it will invalidate that string so it will force the property to change.
public class LocalizationResourceManager : INotifyPropertyChanged
{
public static LocalizationResourceManager Instance { get; } = new LocalizationResourceManager();
public string this[string text]
{
get
{
return AppResources.ResourceManager.GetString(text, AppResources.Culture);
}
}
public void SetCulture(CultureInfo language)
{
Thread.CurrentThread.CurrentUICulture = language;
AppResources.Culture = language;
Invalidate();
}
public event PropertyChangedEventHandler PropertyChanged;
public void Invalidate()
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(null));
}
}
Instead of binding our strings directly to the AppResources class, a Translate Extension that returns a BindingProperty is used and binds to our new LocalizationResourceManager.
[ContentProperty("Text")]
public class TranslateExtension : IMarkupExtension<BindingBase>
{
public string Text { get; set; }
public string StringFormat { get; set; }
object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider)
{
return ProvideValue(serviceProvider);
}
public BindingBase ProvideValue(IServiceProvider serviceProvider)
{
var binding = new Binding
{
Mode = BindingMode.OneWay,
Path = $"[{Text}]",
Source = LocalizationResourceManager.Instance,
StringFormat= StringFormat
};
return binding;
}
}
Usage:
<?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="MultilingualXFSample.Views.ChangeLanguagePage"
xmlns:helpers="clr-namespace:MultilingualXFSample.Helpers">
<Label Text="{helpers:Translate SelectLanguage}" />
</ContentPage>
For more, you can check: Mastering Multilingual in Xamarin.Forms
And there is a sample here: https://github.com/CrossGeeks/MasteringMultilingualSample .

How to bind two different class properties in DataTemplate

I am trying to bind two properties from different classes in DataTemplate.
<DataTemplate x:Key="DemoItemTemplate" x:DataType="local:DemoInfo">
<NavigationViewItem Visibility="{Binding Visibility, Mode=TwoWay}" Content="{x:Bind Name}"/>
</DataTemplate>
DataType set as DemoInfo for this DataTemplate and Name value updated from DemoInfo.
I have tried view model as source and relative source binding. But Visibility property binding not working from ViewModel class. Any suggest how to achieve this?
Visibility="{Binding Visibility, Source={StaticResource viewModel}}"
AFAIK , you cant use multibinding in UWP , you can try to use Locator What is a ViewModelLocator and what are its pros/cons compared to DataTemplates?
How to bind two different class properties in DataTemplate
If you bind Visibility with StaticResource, please declare ViewModel class in your page Resources like the following.
ViewModel
public class ViewModel
{
public ViewModel()
{
Visibility = false;
}
public bool Visibility { get; set; }
}
Xaml
<Page.Resources>
<local:ViewModel x:Key="ViewModel" />
</Page.Resources>
<DataTemplate x:DataType="local:Item">
<TextBlock
Width="100"
Height="44"
Text="{x:Bind Name}"
Visibility="{Binding Visibility, Source={StaticResource ViewModel}}" />
</StackPanel>
</DataTemplate>
Update
If you want Visibility value changed dynamically at run-time, you need implement INotifyPropertyChanged interface for ViewModel class.
public class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
Visibility = false;
}
private bool _visibility;
public bool Visibility
{
get
{
return _visibility;
}
set
{
_visibility = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string PropertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
}
}
For more detail please refer Data binding in depth official document.

Binding two viewModel to one view

i am trying to bind my MasterViewModel where i have initiated two original viewModel to one view. But i am not getting any data so i must be doing the binding wrong. I have found several post
I have tried
in Xaml
<Label
x:Name="SectionRequired"
Grid.Row="2"
HorizontalOptions="End"
IsVisible="{Binding PostViewModel.IsRequired, Source={x:Reference PostViewModel}}"
Text="{x:Static resources:AppResources.AlertRequired}"
TextColor="Red" />
And also followed this solution but i was getting an expcetion that its used lika markup extenstion 'local1:PostViewModel' is used like a markup extension but does not derive from MarkupExtension.
https://stackoverflow.com/questions/50307356/multiple-bindingcontexts-on-same-contentpage-two-different-views
My Master
class MasterPostsViewModel : BaseViewModel
{
public PostViewModel postViewModel { get; set; }
public CategoriesViewModel categoriesViewModel { get; set; }
public MasterPostsViewModel()
{
postViewModel = new PostViewModel();
categoriesViewModel = new CategoriesViewModel();
}
}
}
Conte page
I have set the binding to one field here and that works, buit having to do that for the whole page is not what i want.
MasterPostsViewModel ViewModel;
protected override void OnAppearing()
{
base.OnAppearing();
BindingContext = ViewModel = new MasterPostsViewModel();
NameRequired.IsVisible = ViewModel.postViewModel.IsRequired;
}
Can you help please
instead of
IsVisible="{Binding PostViewModel.IsRequired, Source={x:Reference PostViewModel}}"
just use
IsVisible="{Binding postViewModel.IsRequired}"
your property name is postViewModel is lower case
also, get rid of this line - it will break the binding you have setup in the XAML
NameRequired.IsVisible = ViewModel.postViewModel.IsRequired;

Adding a style to a class defined in a custom UI library

Currently I am working on a UI Library which is supposed to contain custom UI Elements, Layouts and Dialogs in order to have a consistent and reusable UI collection.
In my project, the current structure is as follows:
UILib (Shared Code for the library)
UILib.Droid (android library containing custom renders, etc.)
UILib.iOS (iOS library containing custom renderers, etc.)
UILibDemo (Shared Code for demo application consuming the library)
UILibDemo.Droid (demo application Android)
UILibDemo.iOS (demo application iOS)
In my library I have a class "LoadingDialog", which works fine so far.
However my problem is that I am now trying to define a style to change some properties of the LoadingDialog from within the shared code of the demo application (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:dialogs="clr-namespace:UILib.Dialogs;assembly=UILib"
x:Class="BetterUIDemo.App">
<Application.Resources>
<ResourceDictionary>
<x:String x:Key="DefaultFontLight">OpenSans-Light.ttf</x:String>
<Color x:Key="ThemeColor">#f08c00</Color>
<Color x:Key="BackgroundColor">#37474f</Color>
<Style x:Key="LoadingDialogStyle" TargetType="dialogs:LoadingDialog">
<Setter Property="ThrobberBackgroundColor" Value="White" />
<Setter Property="LabelFontFamily" Value="{DynamicResource DefaultFontLight}" />
<Setter Property="LabelColor" Value="{DynamicResource ThemeColor}" />
<Setter Property="LoadingText" Value="Lade Daten ..." />
</Style>
</ResourceDictionary>
</Application.Resources>
My LoadingDialog class contains these properties as well:
#region Properties
public static BindableProperty ThrobberBackgroundColorProperty = BindableProperty.Create("ThrobberBackgroundColor", typeof(Color), typeof(Color), Color.Black);
public static BindableProperty FontFamilyProperty = BindableProperty.Create("FontFamily", typeof(string), typeof(string), Font.Default.FontFamily);
public static BindableProperty LabelColorProperty = BindableProperty.Create("LabelColor", typeof(Color), typeof(Color), Color.Black);
public static BindableProperty LoadingTextProperty = BindableProperty.Create("LoadingText", typeof(string), typeof(string), "Loading ...");
public string LabelFontFamily
{
get { return (string)GetValue(FontFamilyProperty); }
set { SetValue(FontFamilyProperty, value); }
}
public Color ThrobberBackgroundColor
{
get { return (Color)GetValue(ThrobberBackgroundColorProperty); }
set { SetValue(ThrobberBackgroundColorProperty, value); }
}
public string LoadingText
{
get { return (string)GetValue(LoadingTextProperty); }
set { SetValue(LoadingTextProperty, value); }
}
public Color LabelColor
{
get { return (Color)GetValue(LabelColorProperty); }
set { SetValue(LabelColorProperty, value); }
}
#endregion
However when I try to compile the demo app, I get the following error:
Severity Code Description Project File Line Suppression State
Error Position 14:13. Can't resolve LabelFontFamily on LoadingDialog UILibDemo C:\Work\UILib\UILibDemo\UILibDemo\App.xaml 14
Any suggestions what I might be doing wrong?
I think this could just be a naming thing causing your error.
Bindable Properties use some "Magic" where the Property name and the bindable property need to be named the same thing but the bindable property has the word Property on the end
Notice how your BindableProperty is just called FontFamily
Changing it to the below should fix your error
public static BindableProperty LabelFontFamilyProperty = BindableProperty.Create("LabelFontFamily", typeof(string), typeof(string), Font.Default.FontFamily);
public string LabelFontFamily
{
get { return (string)GetValue(FontFamilyProperty); }
set { SetValue(FontFamilyProperty, value); }
}
Solved it. For further reference:
The issue was a mismatch between the BindableProperty registered as "FontFamily" and the actual property
public string LabelFontFamily
{
get { return (string)GetValue(FontFamilyProperty); }
set { SetValue(FontFamilyProperty, value); }
}
Changing the property to
public string FontFamily
resolved the issue.

WPF - How to bind to a Dependency Property of custom class

I'm once again in WPF binding hell :) I have a public class (Treatment) as follows:
public class Treatment()
{
...
public Ticker SoakTimeActual;
...
}
Within Ticker is a Dependency Property:
public class Ticker : FrameworkElement
{
// Value as string
public static readonly DependencyProperty DisplayIntervalProperty = DependencyProperty.Register("DisplayInterval", typeof(string), typeof(Ticker), null);
public string DisplayInterval
{
get { return (string)GetValue(DisplayIntervalProperty); }
set { SetValue(DisplayIntervalProperty, value); }
}
...
}
In my app, a single Treatment object is created and is meant to be easily accessible in XAML (in app.xaml ):
<Application.Resources>
<ResourceDictionary>
<u:Treatment
x:Key="currentTreatment" />
</ResourceDictionary>
</Application.Resources>
Now, I need to bind to the DisplayInterval dependency property of SoakTimeActual to display this text in its current state. Here is my attempt, which doesn't work:
<TextBlock
Text="{Binding Source={StaticResource currentTreatment}, Path=SoakTimeActual.DisplayInterval}"/>
This, of course, compiles ok, but will not display anything. I'm assuming I've made a mistake with change notification or DataContext or both.
Any insight is appreciated!
WPF binding only operates on properties, not fields.
Therefore, you need change your SoakTimeActual field to a property, like this:
public class Treatment
{
...
public Ticker SoakTimeActual { get; set; }
...
}

Resources