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.
Related
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 .
Update: I've updated this a bit to remove the reference to the error. #michal-diviš gave the correction solution to that. However, my larger issue still remains.
I'm new to Xamarin and trying to learn by making a simple email client. I'm trying to set a property on a ContentPage I have created.
The Setup
The MainPage simply has a grid with two columns; the left side features an CollectionView of the inbox, the right side is my custom ContentPage MessageDisplayView. When an email is clicked in the CollectionView, the CurrentMessage property on the MainPageViewModel is updated to the selected item.
The Issue
I'm trying to bind the property MessageDisplayView.Message to the MainPageViewModel.CurrentMessage property, but the contentpage never updates. I've tried with and without BindableProperty, as well as other ideas found while searching Google and Stackoverflow.
The Question
How do I handle setting and updating a property that I would like to live with the ContentPage?
The Code
MainPage.xaml
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:c="Microsoft.Toolkit.Uwp.UI.Controls"
xmlns:vm="clr-namespace:Project.ViewModel"
xmlns:view="clr-namespace:Project.View"
xmlns:fa="clr-namespace:FontAwesome"
x:Class="Project.MainPage">
<ContentPage.BindingContext>
<vm:MainPageViewModel/>
</ContentPage.BindingContext>
<ContentPage.Resources>
<ResourceDictionary>
<ResourceDictionary Source="ResourceDictionaries/EmailResourceDictionary.xaml"/>
</ResourceDictionary>
</ContentPage.Resources>
<Grid x:Name="MainPageGrid">
<!-- other xaml code -->
<view:MessageDisplayView
x:Name="MyDisplayView"
Grid.Column="1"
Message="{Binding CurrentMessage}" <!-- Error -->
/>
</Grid>
</ContentPage>
MainPageViewModel.cs
using MimeKit;
using Project.EmailLogic;
using System.Collections.ObjectModel;
using System.Windows.Input;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace Project.ViewModel
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public class MainPageViewModel: ObservableObject
{
private MimeMessage currentMessage;
public MimeMessage CurrentMessage
{
get => currentMessage;
set => SetProperty(ref currentMessage, value, nameof(MessageDisplayView.Message));
}
public MainPageViewModel()
{
}
}
}
MessageDisplayView.xaml
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:view="clr-namespace:Project.View"
xmlns:vm="clr-namespace:Project.ViewModel"
x:DataType="view:MessageDisplayView"
xmlns:fa="clr-namespace:FontAwesome"
x:Class="Project.View.MessageDisplayView">
<ContentView.Content>
<Grid>
<!-- Various standard xaml things, for example... -->
<!-- Subject Line -->
<Label x:Name="SubjectLine"
Grid.Row="1"
Text="{Binding Message.Subject}"
/>
</Grid>
</ContentView.Content>
</ContentView>
MessageDisplayView.xaml.cs
using MimeKit;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace Project.View
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MessageDisplayView : ContentView
{
private MimeMessage message;
public MimeMessage Message
{
get
{
return (MimeMessage)GetValue(MessageProperty);
}
set
{
SetValue(MessageProperty, value);
BodyHtmlViewSource.Html = Message.HtmlBody;
}
}
public BindableProperty MessageProperty =
BindableProperty.Create(nameof(Message), typeof(MimeMessage), typeof(MessageDisplayView));
public HtmlWebViewSource BodyHtmlViewSource { get; set; }
public MessageDisplayView()
{
InitializeComponent();
}
}
}
The problem was the BindableObject was not hearing the notifications of the property changing.
The solution was to add the OnPropertyChanged method to the code behind of the ContentView, not the ContentPageViewModel.
This "solution" correctly updates the property in the code, but it does not update the xaml/UI. I think this might a separate issue.
This confused me at first, when #michal-diviš pointed out the OnPropertyChanged calls, as I thought I was suppose to wire up the event subscription myself in the ContentView code behind. But after stumbling across this article, I realized that the method was required elsewhere.
I feel like a major issue is that there isn't a lot of information about passing data or properties between elements/UserControls/ContentPages, etc. Over the last two days, I've read and watched a fair amount on BindableProperties, but seen very little use of OnPropertyChanged or updating the properties from elsewhere. Perhaps I'm missing the places where it's talked about, or maybe it's more easy or obvious than I realize, but in hindsight, this seems like something that should have been mentioned in every BindableProperty 101.
Beyond the official documentation of course, if anyone knows a good article or video going over sharing/binding/updating properties between classes/views/whatever, I'd love to check that out.
Here's an example of the final, working code:
public partial class MessageDisplayView : ContentView
{
public MimeMessage Message
{
get
{
return (MimeMessage)GetValue(MessageProperty);
}
set
{
SetValue(MessageProperty, value);
}
}
public static BindableProperty MessageProperty =
BindableProperty.Create(nameof(Message), typeof(MimeMessage), typeof(MessageDisplayView), new MimeMessage(),
BindingMode.TwoWay);
protected override void OnPropertyChanged(string propertyName = null)
{
base.OnPropertyChanged(propertyName);
if (propertyName == MessageProperty.PropertyName)
{
if(Message != null)
{
// Update ContentView properties and elements.
}
}
}
Thank you again to #michal-diviš for your help!
Fix
It's the BindableProperty definition!
You have (in the MessageDisplayView.xaml.cs):
public BindableProperty MessageProperty = BindableProperty.Create(nameof(Message), typeof(MimeMessage), typeof(MessageDisplayView));
you need to make it static readonly like this:
public static readonly BindableProperty MessageProperty = BindableProperty.Create(nameof(Message), typeof(MimeMessage), typeof(MessageDisplayView));
Usage of INotifyPropertyChanged
The CurrentMessage property in your MainPageViewModel seems to be the problem. You've created it as a BindableProperty, however, that's meant to be used by user controls, not view models.
What you need in the view model is to implement the INotifyPropertyChanged interface and invoke the PropertyChanged event in the property setter. That is done so the UI will update itseld whenever the CurrentMessage property changes.
Tweak your MainViewModel.cs like this:
using MimeKit;
using Project.EmailLogic;
using Xamarin.Forms;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace Project.ViewModel
{
public class MainPageViewModel : INotifyPropertyChanged
{
private MimeMessage currentMessage;
public MimeMessage CurrentMessage
{
get => currentMessage;
set {
currentMessage = value;
OnPropertyChanged(nameof(CurrentMessage))
};
}
public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = "") =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
In this example, I've implemented the INotifyPropertyChanged directly in you view model, but a better way to do it is to inherit from a base class that already has that implemented, like this one: ObservableObject from James Montemagno's MVVM Helpers library. The resulting view model would look like this:
using MimeKit;
using Project.EmailLogic;
using MvvmHelpers;
namespace Project.ViewModel
{
public class MainPageViewModel : ObservableObject
{
private MimeMessage currentMessage;
public MimeMessage CurrentMessage
{
get => currentMessage;
set => SetProperty(ref currentMessage, value);
}
}
}
EDIT:
Lately I've been using the CommunityToolkit.Mvvm library instead of Refactored.MvvmHelpers as it's more updated and feature rich.
The line Resources.Add("eventAggregator", Container.Resolve()); raises Null exception.
UPDATE
I've added all classes to explain more. As #Axemasta said, there is no need to register IEventAggregator and I removed registration. Now I don't how to connect the Listview EventAggregator behavior to the EventAggregator.
This is whole App.xaml code file.
public partial class App : PrismApplication
{
/*
* The Xamarin Forms XAML Previewer in Visual Studio uses System.Activator.CreateInstance.
* This imposes a limitation in which the App class must have a default constructor.
* App(IPlatformInitializer initializer = null) cannot be handled by the Activator.
*/
public App() : this(null) { }
public App(IPlatformInitializer initializer) : base(initializer) { }
protected override async void OnInitialized()
{
InitializeComponent();
Resources.Add("eventAggregator", Container.Resolve<IEventAggregator>());// Removed on update
FlowListView.Init();
await NavigationService.NavigateAsync("NavigationPage/MainPage");
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation<NavigationPage>();
containerRegistry.RegisterForNavigation<MainPage>();
}
}
}
The behavior class:
public class ScrollToMyModelBehavior : BehaviorBase<ListView>
{
private IEventAggregator _eventAggregator;
public IEventAggregator EventAggregator
{
get => _eventAggregator;
set
{
if (!EqualityComparer<IEventAggregator>.Default.Equals(_eventAggregator, value))
{
_eventAggregator = value;
_eventAggregator.GetEvent<ScrollToMyModelEvent>().Subscribe(OnScrollToEventPublished);
}
}
}
private void OnScrollToEventPublished(ListItem model)
{
AssociatedObject.ScrollTo(model, ScrollToPosition.Start, true);
}
protected override void OnDetachingFrom(ListView bindable)
{
base.OnDetachingFrom(bindable);
// The Event Aggregator uses weak references so forgetting to do this
// shouldn't create a problem, but it is a better practice.
EventAggregator.GetEvent<ScrollToMyModelEvent>().Unsubscribe(OnScrollToEventPublished);
}
}
The Event class:
public class ScrollToMyModelEvent : PubSubEvent<ListItem>
{
}
The page view model:
public MainPageViewModel(INavigationService navigationService, IEventAggregator eventAggregator)
: base (navigationService)
{
Title = "صفحه اصلی";
ListHeight = 100;
ListWidth = 250;
_eventAggregator = eventAggregator;
Items items = new Items();
ListViewItemSouce = items.GetItems();
MyModels = items.GetItems();
SelectedModel = ListViewItemSouce[3];
_eventAggregator.GetEvent<ScrollToMyModelEvent>().Publish(SelectedModel);
}
The page view:
<StackLayout HorizontalOptions="Center" VerticalOptions="Center" WidthRequest="{Binding ListWidth}" HeightRequest="{Binding ListHeight}"
Grid.Row="1" Grid.Column="1">
<local:NativeListView x:Name="lst3" ItemsSource="{Binding ListViewItemSouce}" Margin="1" BackgroundColor="Transparent" RowHeight="47" HasUnevenRows="false">
<ListView.Behaviors>
<local:ScrollToMyModelBehavior EventAggregator="{StaticResource eventAggregator}" /> // Error raised that there is not such a static property
</ListView.Behaviors>
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Word}" TextColor="Black"/>
</DataTemplate>
</ListView.ItemTemplate>
</local:NativeListView>
</StackLayout>
You do not need to register IEventAggregator when the app initialises, much like INavigationService or IPageDialog, you can use it straight out of the box!
To use EventAggregator you should do the following things:
Create an Event
You will first need to create an Event (using Prism) that you can pass to the EventAggregator. Your event should inherit from PubSubEvent, you can pass this an object (optional). So your event would look like this:
using System;
using Prism.Events;
namespace Company.App.Namespace.Events
{
public class SampleEvent : PubSubEvent
{
}
}
Looking at a recent app, I most commonly use this when passing data between custom popup views (like a dictionary of params).
Subscribe to the Event
When IEventAggregator fires, anything that has subscribe to the event will execute any code specified. In the class you want to recieved the event you will have to do the following:
Pass the class IEventAggregator through the constructor (prism does the DI afterall)
Initialise a local IEventAggregator for use in this class
Subscribe IEventAggregator to a handler method.
Here is what the code may look like:
public class TheClassListeningForAnEvent
{
private readonly IEventAggregator _eventAggregator;
public TheClassListeningForAnEvent(IEventAggregator eventAggregator)
{
_eventAggregator = eventAggregator;
_eventAggregator.GetEvent<SampleEvent>().Subscribe(OnEventRecieved);
}
void OnEventRecieved()
{
//Do something here
}
}
Fire the Event
Now you have registered for the event, you can fire the event. Pass the IEventAggregator into whatever class you want to fire the event from and use the Publish Method:
public class TheClassPublishingAnEvent
{
private readonly IEventAggregator _eventAggregator;
public TheClassListeningForAnEvent(IEventAggregator eventAggregator)
{
_eventAggregator = eventAggregator;
_eventAggregator.GetEvent<SampleEvent>().Publish();
}
}
Thats the long and the short of it. You could pass anything to the IEventAggregator, you would just need to handle for this in the methods you are subscribing.
Hopefully that is enough to get you going using IEventAggregator!
Just verify if you are adding below code in IOS, Android and UWP projects.
IOS- Appdelegate
public class AppdelegateInitializer : IPlatformInitializer
{
public void RegisterTypes(IUnityContainer container)
{
}
}
Android - MainActivity
public class MainActivityInitializer : IPlatformInitializer
{
public void RegisterTypes(IUnityContainer container)
{
}
}
UWP-- MainPage.cs
public class UwpInitializer : IPlatformInitializer
{
public void RegisterTypes(IUnityContainer container)
{
}
}
My guidance on this has evolved as features have been added to Prism to make this sort of thing even easier.
In the past the reason you would resolve and add the IEventAggregator as a StaticResource is that there was no way to inject this. We now have the ContainerProvider which amazingly allows you to add types in XAML that require Dependency Injection. To start you can refactor your ScrollToBehavior to use a DI Pattern by adding the IEventAggregator as a constructor parameter, removing the Bindable Property (if you choose).
public class ScrollToBehavior : BehaviorBase<ListView>
{
private IEventAggregator _eventAggregator { get; }
public ScrollToBehavior(IEventAggregator eventAggregator)
{
_eventAggregator = eventAggregator;
}
}
As I mentioned you can use the ContainerProvider in XAML to resolve and provide a type that requires DI, as follows:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:ioc="clr-namespace:Prism.Ioc;assembly=Prism.Forms"
xmlns:behavior="using:AwesomeProject.Behaviors
x:Class="AwesomeProject.Views.ViewA">
<ListView>
<ListView.Behaviors>
<ioc:ContainerProvider x:TypeArguments="behavior:ScrollToBehavior" />
</ListView.Behaviors>
</ListView>
</ContentPage>
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; }
...
}
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.