I achieved Dynamic Localization in Silverlight using the following blog post:
http://www.wintellect.com/CS/blogs/jprosise/archive/2010/06/21/dynamic-localization-in-silverlight.aspx
The solution works great. I can change my Language options and it works perfectly.
But as mentioned in the article i cannot get the design time support.
I designed a Resource Wrapper class for this:
public sealed class ResourceWrapper
{
//private static readonly ObservableResources<Resources> appResources = new ObservableResources<Resources>(resx);
private ObservableResources<Resources> appResources = new ObservableResources<Resources>(new Resources());
public ObservableResources<Resources> ApplnResources
{
get { return appResources; }
}
public event PropertyChangedEventHandler PropertyChanged;
public void UpdateBindings()
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("ApplnResources"));
}
}
}
In my app.xaml i added the ResourceWrapper class
In my Home.xaml i added the following lines of code:
<HyperlinkButton Content="{Binding Source={StaticResource ResourceWrapper},Path=ApplnResources.LocalizationResources.CommentsEntry/>
By doing this i got my design time support back. But now when i run my application and change my Language it does not change?
can somebody help me with this solution?
Your class ResourceWrapper should implement INotifyPropertyChanged event. Otherwise binding updating will not hook up.
Related
I'm new to .Net Maui but have completed James Montemagno's 4 hour Workshop. Included in the Workshop was:
Creating a Page with a CollectionView
Creating a ViewModel
Creating an async method which calls a data service to retrieve data
Configuring the async method as a ICommand
Binding the data model list to the CollectionView
Binding the Command to a Button
Clicking the button works and populates the CollectionView. How would I go about removing the button and performing this action when the page opens? Note I tried modifying the method by removing the "[ICommand]" which did not work. Also, should this action be done in the Code Behind or in the ViewModel?
Thanks in advance for assistance!
(ModelView)
public partial class FieldAssignedWbsViewModel : BaseViewModel
{
FieldAssignedWbsService fieldAssignedWbsService;
public ObservableCollection<FieldAssignedWbs> WbsList { get; set; } = new();
public FieldAssignedWbsViewModel(FieldAssignedWbsService fieldAssignedWbsService)
{
Title = "Wbs Assigned";
this.fieldAssignedWbsService = fieldAssignedWbsService;
}
[ICommand]
async Task GetFieldAssignedWbsListAsync()
{
if (IsBusy)
return;
try
{
IsBusy = true;
var wbsList = await fieldAssignedWbsService.GetFieldAssignedWbsList();
if (WbsList.Count != 0)
WbsList.Clear();
foreach (var wbs in wbsList)
WbsList.Add(wbs);
}
catch (Exception ex)
{
Debug.WriteLine(ex);
await Shell.Current.DisplayAlert("Error!",
$"Undable to get monkeys: {ex.Message}", "OK");
}
finally
{
IsBusy = false;
}
}
}
(CollectionView Binding)
<CollectionView BackgroundColor="Transparent"
ItemsSource="{Binding WbsList}"
SelectionMode="None">
(Code behind page with incorrect call to Command Method)
public partial class FieldAssignedWbsPage : ContentPage
{
public FieldAssignedWbsPage(FieldAssignedWbsViewModel viewModel)
{
InitializeComponent();
BindingContext = viewModel;
//The following call does not work
//Hover message: Non-invocable member... cannot be called like a method
await viewModel.GetFieldAssignedWbsListCommand();
}
}
Although the original answer is very valid, I'd recommend installing the CommunityToolkit.Maui (by Microsoft), then using its EventToCommand features.
After installing, add builder.UseMauiCommunityToolkit() to CreateMauiApp() method in MauiProgram.cs.
Then, in relevant XAML page, add this namespace xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit" and then you should be able to use this block of code to do what you want:
<ContentPage.Behaviors>
<toolkit:EventToCommandBehavior
EventName="Appearing"
Command="{Binding GetFieldAssignedWbsListCommand}" />
</ContentPage.Behaviors>
Sorry that this is a bit late, I just believe that it is a slightly cleaner solution as it avoids populating the code-behind with any code and keeps UI handling purely between the viewmodel and the view.
use OnAppearing. You may also need to make the GetFieldAssignedWbsList public
protected override async void OnAppearing()
{
await viewModel.GetFieldAssignedWbsListCommand.Execute(null);
}
I've got Xamarin.Forms project with pcl-part and native win, ios and android parts.
All page structure and view-models are in pcl-part. App work's fine, but when I'm trying for example to hide Grid from code behind - it do nothing. Here is code example:
Xaml:
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="SomeNamespase.SomePage">
<Grid x:Name="InnerGrid" BackgroundColor="Green">
<Frame x:Name="InnerContent"/>
</Grid>
</ContentPage>
.cs :
using System;
namespace SomeNamespase
{
public partial class SomePage : ContentPage
{
public void SomeMethod()
{
this.InnerGrid.IsVisible = false;
this.InnerContent.BackgroundColor = Color.Aqua;
}
}
}
I've also tried this.FindByName<Grid>("InnerGrid"); the same result
Note: if I am trying to get controls from action in PCL everything is good. Nothing going on when I'm trying to get controls from ViewPresenter in windows (or other platforms) project.
You need to make sure you are properly implementing INotifyPropertyChanged
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Please try the below code, as in your code I can't see the constructor.
using System;
namespace SomeNamespase
{
public partial class SomePage : ContentPage
{
public SomePage()
{
SomeMethod() ;
}
public void SomeMethod()
{
this.InnerGrid.IsVisible = false;
this.InnerContent.BackgroundColor = Color.Aqua;
}
}
}
I use SimpleInjector in mvc with this code
public static class SimpleInjectorInitializer
{
public static void Initialize()
{
var container = new Container();
InitializeContainer(container);
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
container.Verify();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
}
private static void InitializeContainer(Container container)
{
container.Register<IPersonRepository, PersonEntityRepository>();
}
}
but now I want to test LightInject Ioc in my mvc application but How ?
I wrote this code
[assembly: WebActivator.PostApplicationStartMethod(typeof(LightInjectInitializer), "InitializeLI")]
public static class LightInjectInitializer
{
public static void InitializeLI()
{
var container = new ServiceContainer();
InitializeContainer(container);
container.RegisterControllers(Assembly.GetExecutingAssembly());
container.EnableMvc();
}
private static void InitializeContainer(ServiceContainer container)
{
container.Register(typeof(PersonEntityRepository), typeof(IPersonRepository), new PerScopeLifetime());
}
}
but show me this error
No parameterless constructor defined for this object.
Can anyone help me for writing equivalent code that working in MVC ?
Sample Code : Download
I am the author of LightInject and would like to help you out.
This static initialize method? Where is it called from.
The reason that you get this error is probably because the initialize code did not execute.
If you would like further assistance, it would be valuable to see what you have in global.asax.cs.
This page also contains information about how to set this up.
http://www.lightinject.net/#mvc
Please change the controller registration line to:
container.RegisterControllers(typeof(MVCApplicationNamespace.Controllers.HomeController).Assembly);
Question about binding in XAML with WP8.
In my App.cs I declare a public property for class Setting. In other xaml pages I need to access that propery and pass that property to a ConverterParameter. I can't say I've found a clean way of doing this. Below is my current method of how I accomplish this, but it just feels dirty. Any other ways out there?
So what's happening with code below? In app the settings data gets loaded. Any time the settings gets loaded or the a setting changes it Removes/Adds App.Current.Resource. This then allows me to data bind it {StaticResource {resourceName}}
Again, this works 100%...but is there a better/another way to accomplish this?
App.cs
private static Settings _settings = null;
public static Settings Settings
{
get { return _settings; }
private set { _settings = value; }
}
private async void Application_Launching(object sender, LaunchingEventArgs e)
{
if (Settings == null)
Settings = await FlightPath.Core.Data.LoadSettingsAsync();
App.Current.Resources.Add("Settings", App.Settings);
Settings.SettingsChanged += Settings_SettingsChanged;
}
private void Settings_SettingsChanged(object sender, EventArgs e)
{
if (App.Current.Resources["Settings"] == null)
App.Current.Resources.Add("Settings", App.Settings);
else
{
App.Current.Resources.Remove("Settings");
App.Current.Resources.Add("Settings", App.Settings);
}
}
Application Page XAML using Converter / ConverterParameter
<TextBlock Text="{Binding observation_time,
Converter={StaticResource ZuluToLocalTimeConverter},
ConverterParameter={StaticResource Settings}}"
Style="{StaticResource PhoneTextNormalStyle}"
Margin="-4,0,0,0"/>
if you are using MVVM you can Create a SettingManager class which having a Singleton instance. Then declare its propert in ViewModelBase class. Finally use it into your xaml code
XAML
C#
class ViewModelBaseClass: InotifyPropertyChanged
{
public SettingManager Settings{get{return SettingManager.Instance;}}
}
class SettingManager
{
public static Instance{get{...}}
public string this[string sName]
{
return "whatever you need";
}
}
class MYViewModel: ViewModelBase
{
}
Abstracting commands into the View Model is a valuable practice with XAML/MVVM projects. I get that. And, I see ICommand in in WinRT; but, how do we implement it? I haven't found a sample that actually works. Anyone know?
My all time favorite has to be the DelegateCommand provided by the Microsoft Patterns and Practices team. It allows you to create a typed command:
MyCommand = new DelegateCommand<MyEntity>(OnExecute);
...
private void OnExecute(MyEntity entity)
{...}
It also provides a way to raise the CanExecuteChanged event (to disable/enable the command)
MyCommand.RaiseCanExecuteChanged();
Here's the code:
public class DelegateCommand<T> : ICommand
{
private readonly Func<T, bool> _canExecuteMethod;
private readonly Action<T> _executeMethod;
#region Constructors
public DelegateCommand(Action<T> executeMethod)
: this(executeMethod, null)
{
}
public DelegateCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod)
{
_executeMethod = executeMethod;
_canExecuteMethod = canExecuteMethod;
}
#endregion Constructors
#region ICommand Members
public event EventHandler CanExecuteChanged;
bool ICommand.CanExecute(object parameter)
{
try
{
return CanExecute((T)parameter);
}
catch { return false; }
}
void ICommand.Execute(object parameter)
{
Execute((T)parameter);
}
#endregion ICommand Members
#region Public Methods
public bool CanExecute(T parameter)
{
return ((_canExecuteMethod == null) || _canExecuteMethod(parameter));
}
public void Execute(T parameter)
{
if (_executeMethod != null)
{
_executeMethod(parameter);
}
}
public void RaiseCanExecuteChanged()
{
OnCanExecuteChanged(EventArgs.Empty);
}
#endregion Public Methods
#region Protected Methods
protected virtual void OnCanExecuteChanged(EventArgs e)
{
var handler = CanExecuteChanged;
if (handler != null)
{
handler(this, e);
}
}
#endregion Protected Methods
}
Check out RelayCommand class (only METRO code). The NotifyPropertyChanged class can be found here. The NotifyPropertyChanged class is only used to allow bindings on CanExecute and update it with RaiseCanExecuteChanged.
The original relay command class can be found here
Unfortunately there does not seem to be a native class that implements it for you. The interface is not overly complicated if you want to implement it yourself, and the popular MVVM Lite toolkit includes its own version of RelayCommand. You can add MVVM Lite to your project by right-clicking on References and choosing "Manage NuGet Packages". If you don't have this option, enable Nuget under Tools -> Extensions and Updates.
I've been looking for a minimal end-to-end implementation of a XAML-MVVM command, and not found it yet.
So, following #Rico's answer I ended up with the following as a minimal RelayCommand which works. I use a similar minimal version in a large project.
public class RelayCommand : System.Windows.Input.ICommand {
readonly Action<object> execute;
public RelayCommand(Action<object> execute) {
this.execute = execute;
}
public bool CanExecute(object parameter) {
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter) {
this.execute(parameter);
}
}
The larger RelayCommand class seems to provide more control over CanExecute and CanExecuteChanged, but you don't need that to get started - and you may not need it at all.
To use it in a view model:
class ViewModel : INotifyPropertyChanged {
<< ... snip VM properties and notifications ...>>
public RelayCommand DoSomethingCommand {
get {
return new RelayCommand(param => {
this.DoSomething(param as AType);
Debug.WriteLine("Command Executed");
});
}
}
}
(We don't need the INotifyPropertyChanged for the Command, but any view model typically implements it.)
Finally, the XAML...
<Grid>
<!-- Set the data context here, for illustration. -->
<Grid.DataContext>
<local:ViewModel/>
</Grid.DataContext>
<!-- A sample control bind to a property -->
<TextBlock
Text="{Binding AProp}"/>
<!-- Bind a command -->
<Button Command="{Binding DoSomethingCommand}" CommandParameter="foo">Change!</Button>
</Grid>
I found this really good example at
https://code.msdn.microsoft.com/windowsapps/Working-with-ICommand-690ba1d4
<Page.Resources>
<local:MyCommandsCollection x:Key="MyCommands" />
</Page.Resources>
<Button Width="280"
Height="59"
Margin="513,280,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Command="{Binding MyFirstCommand}"
CommandParameter="{Binding Text,
ElementName=myTextBox}"
Content="Execute Command" />
public class MyCommandsCollection
{
public MyCommand MyFirstCommand
{
get { return new MyCommand(); }
}
}
public class MyCommand : ICommand
{
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public async void Execute(object parameter)
{
MessageDialog message = new MessageDialog(
"The command is executing, the value of the TextBox is " + parameter as String);
await message.ShowAsync();
}
}
I tried this out with x:Bind and it works nicely. All I need is to expose a property in my ViewModel that returns a new Instance of the "MyCommand" class and it's all good.
Since I'm setting the DataContext in my XAML, I didn't need to mess with any of the "MyCommandCollection" stuff. Yay compiled binding.