Full RelayCommand in F#? - f#

I am new to F#. As a learning experiment, I am rewriting a C# application in pure F#. How can the "RelayCommand" , RelayCommand, of C# be written in F# ?
Any help is most appreciated.
TIA
As requested, this is the RelayCommand I've been using in C#. :( It seems overly complicated. (There must surely be a simpler one!).
public class RelayCommand<T> : ICommand
{
private readonly WeakAction<T> _execute;
private readonly WeakFunc<T, bool> _canExecute;
public RelayCommand(Action<T> execute)
: this(execute, null)
{
}
public RelayCommand(Action<T> execute, Func<T, bool> canExecute)
{
if (execute == null)
{
throw new ArgumentNullException("execute");
}
_execute = new WeakAction<T>(execute);
if (canExecute != null)
{
_canExecute = new WeakFunc<T, bool>(canExecute);
}
}
public event EventHandler CanExecuteChanged
{
add
{
if (_canExecute != null)
{
CommandManager.RequerySuggested += value;
}
}
remove
{
if (_canExecute != null)
{
CommandManager.RequerySuggested -= value;
}
}
}
public void RaiseCanExecuteChanged()
{
CommandManager.InvalidateRequerySuggested();
}
public bool CanExecute(object parameter)
{
if (_canExecute == null)
{
return true;
}
if (_canExecute.IsStatic || _canExecute.IsAlive)
{
if (parameter == null && typeof(T).IsValueType)
{
return _canExecute.Execute(default(T));
}
if (parameter == null || parameter is T)
{
return (_canExecute.Execute((T)parameter));
}
}
return false;
}
public virtual void Execute(object parameter)
{
var val = parameter;
if (CanExecute(val)
&& _execute != null
&& (_execute.IsStatic || _execute.IsAlive))
{
if (val == null)
{
if (typeof(T).IsValueType)
{
_execute.Execute(default(T));
}
else
{
// ReSharper disable ExpressionIsAlwaysNull
_execute.Execute((T)val);
// ReSharper restore ExpressionIsAlwaysNull
}
}
else
{
_execute.Execute((T)val);
}
}
}
}
public class WeakFunc<TResult>
{
private Func<TResult> _staticFunc;
/// <summary>
/// Gets or sets the <see cref="MethodInfo" /> corresponding to this WeakFunc's
/// method passed in the constructor.
/// </summary>
protected MethodInfo Method
{
get;
set;
}
/// <summary>
/// Get a value indicating whether the WeakFunc is static or not.
/// </summary>
public bool IsStatic
{
get
{
return _staticFunc != null;
}
}
public virtual string MethodName
{
get
{
if (_staticFunc != null)
{
return _staticFunc.Method.Name;
}
return Method.Name;
}
}
protected WeakReference FuncReference
{
get;
set;
}
protected WeakReference Reference
{
get;
set;
}
protected WeakFunc()
{
}
public WeakFunc(Func<TResult> func)
: this(target: func?.Target, func: func)
{
}
public WeakFunc(object target, Func<TResult> func)
{
if (func.Method.IsStatic)
{
_staticFunc = func;
if (target != null)
{
// Keep a reference to the target to control the
// WeakAction's lifetime.
Reference = new WeakReference(target);
}
return;
}
Method = func.Method;
FuncReference = new WeakReference(func.Target);
Reference = new WeakReference(target);
}
public virtual bool IsAlive
{
get
{
if (_staticFunc == null
&& Reference == null)
{
return false;
}
if (_staticFunc != null)
{
if (Reference != null)
{
return Reference.IsAlive;
}
return true;
}
return Reference.IsAlive;
}
}
public object Target
{
get
{
if (Reference == null)
{
return null;
}
return Reference.Target;
}
}
protected object FuncTarget
{
get
{
if (FuncReference == null)
{
return null;
}
return FuncReference.Target;
}
}
public TResult Execute()
{
if (_staticFunc != null)
{
return _staticFunc();
}
var funcTarget = FuncTarget;
if (IsAlive)
{
if (Method != null
&& FuncReference != null
&& funcTarget != null)
{
return (TResult)Method.Invoke(funcTarget, null);
}
}
return default(TResult);
}
public void MarkForDeletion()
{
Reference = null;
FuncReference = null;
Method = null;
_staticFunc = null;
}
}
As a newbie to F#, how can this be implemented? How does F# deal with "WeakAction"?
Thank you.

Related

Why Vaadin TreeGrid loads the data two times after Scrolling?

I have the following issue: When my Treegrid gets loaded for the first time, all the root data where correct added. But when i scroll drown in the TreeGrid, the data are picked up again and added to the Treegrid.
Does anyone know how to deactivate lazy loading in a Treegrid when scrolling?
Here is my Method which created the Treegrid
private Component createCategoriesTree() {
treeGrid.setHeight("100%");
treeGrid.addComponentHierarchyColumn(productCategory -> getProductCategoryName(productCategory)).setHeader("Kategorie").setSortable(false);
ProductCategory root = productCategoriesService.getRootCategory();
HierarchicalDataProvider dataProvider = new AbstractBackEndHierarchicalDataProvider<ProductCategory, Void>() {
#Override
public int getChildCount(HierarchicalQuery<ProductCategory, Void> query) {
if (query.getParent() == null) {
List<ProductCategory> list = productCategoriesService.findByParentId(root.getId());
return (int) list.size();
} else {
List<ProductCategory> list = productCategoriesService.findByParentId(query.getParent().getId());
return (int) list.size();
}
}
#Override
public boolean hasChildren(ProductCategory item) {
List<ProductCategory> list = productCategoriesService.findByParentId(item.getId());
if (list != null && list.size() > 0) {
return true;
} else {
return false;
}
}
#Override
protected Stream<ProductCategory> fetchChildrenFromBackEnd(HierarchicalQuery<ProductCategory, Void> query) {
if (query.getParent() == null) {
return productCategoriesService.findByParentId(root.getId()).stream();
} else {
return productCategoriesService.findByParentId(query.getParent().getId()).stream();
}
}
};
treeGrid.setDataProvider(dataProvider);
return treeGrid;
}
The issue was:
missing skip method like following method body:
#Override
protected Stream<ProductCategory> fetchChildrenFromBackEnd(HierarchicalQuery<ProductCategory, Void> query) {
if (query.getParent() == null) {
return productCategoriesService.findByParentIdOrderByCategoryNameAsc(root.getId()).stream().skip(query.getOffset()).limit(query.getLimit()); //THIS
} else {
return productCategoriesService.findByParentIdOrderByCategoryNameAsc(query.getParent().getId()).stream(); //THIS
}
}

How to create a unique session for a user: ASP.NET

I have been learning ASP.NET and came to point where I realised that my web application is creating only a static session for all the users, that is if one logs out all the users are logged out, and sometimes the session is even swapped (lets say userA logs in and right after userB logs in, when the userA refreshes he is seeing the data of userB).
My SessionManager class is as below
SessionManager.cs
public class SessionManager
{
#region Private Data
private static String USER_KEY = "user";
#endregion
public static Employee CurrentUser
{
get;
set;
}
public static string UserType
{
get;
set;
}
public static Int32 SessionTimeout
{
get
{
return System.Web.HttpContext.Current.Session.Timeout;
}
}
public static String GetUserFullName()
{
if (SessionManager.CurrentUser != null)
return SessionManager.CurrentUser.FirstName;
else
return null;
}
public static Boolean IsUserLoggedIn
{
get
{
if (SessionManager.CurrentUser != null)
return true;
else
return false;
}
}
#region Methods
public static void AbandonSession()
{
for (int i = 0; i < System.Web.HttpContext.Current.Session.Count; i++)
{
System.Web.HttpContext.Current.Session[i] = null;
}
System.Web.HttpContext.Current.Session.Abandon();
}
#endregion
}
Login Controller:
[HttpPost]
public ActionResult Index(String txtUserName, String txtPassword)
if (User.Identity.IsAuthenticated)
{
return View();
}
else
{
if (ModelState.IsValid)
{
Employee obj = (from o in db.Employees
where o.Email == txtUserName && o.Password == txtPassword
select o).FirstOrDefault();
if (obj != null)
{
var dh = db.Departments.Where(x => x.LeadBy == obj.EmployeeId).FirstOrDefault();
var tl = db.Teams.Where(x => x.LeadBy == obj.EmployeeId).FirstOrDefault();
if (dh == null && tl == null)
{
Session["UserType"] = "EMP";
}
else if (dh != null && tl != null)
{
Session["UserType"] = "DH&TL";
}
else if (dh != null)
{
Session["UserType"] = "DH";
}
else if (tl != null)
{
Session["UserType"] = "TL";
}
SessionManager.CurrentUser = obj; //how can I create different obj for different users here?
var currentEnrollID = SessionManager.CurrentUser.EnrollNumber;
var currentEmployeeID = SessionManager.CurrentUser.EmployeeId;
var currentEmpName = SessionManager.CurrentUser.FirstName + " " + SessionManager.CurrentUser.LastName;
I have been using sessions like this in the whole application so a different approach would be hectic to amend the changes.
public ActionResult Logout()
{
if (SessionManager.IsUserLoggedIn)
{
SessionManager.CurrentUser.EmployeeId = 0;
SessionManager.AbandonSession();
Session.Clear();
Session.Abandon();
Session.RemoveAll();
}
return RedirectToAction("Index","Login");
}
This is not related to ASP.NET, but it is more on how static members work.
The real issue is your SessionsManager, which contains static methods that you store values every time the user logs-in. This means the same instance is shared across different session in the application.
I have an update SessionManager you can see below. I have stored the SessionManager object in the session object so that as long the session is alive. It will return the same instance by session when you call it using SessionManager.Current.
public class SessionManager {
#region Private Data
private static String USER_KEY = "user";
#endregion
public static SessionManager Current {
get{
if (HttpContext.Current.Session[USER_KEY] != null) {
return (SessionManager) HttpContext.Current.Session[USER_KEY];
} else {
var sess = new SessionManager ();
HttpContext.Current.Session[USER_KEY] = sess;
return sess;
}
}
}
public Employee CurrentUser {
get;
set;
}
public string UserType {
get;
set;
}
public Int32 SessionTimeout {
get {
return System.Web.HttpContext.Current.Session.Timeout;
}
}
public String GetUserFullName () {
if (SessionManager.Current.CurrentUser != null)
return SessionManager.Current.CurrentUser.FirstName;
else
return null;
}
public Boolean IsUserLoggedIn {
get {
if (SessionManager.Current.CurrentUser != null)
return true;
else
return false;
}
}
#region Methods
public void AbandonSession () {
for (int i = 0; i < System.Web.HttpContext.Current.Session.Count; i++) {
System.Web.HttpContext.Current.Session[i] = null;
}
System.Web.HttpContext.Current.Session.Abandon ();
}
#endregion
}

Listview Filter with SearchView Using Base Adapter in Xamarin android Error

I am try to filter listview with searchview using Base Adapter in in xamarin Android, My listView Bind in sql server using restfull web service i am stuck in PublishResults which is given an error
Here Is My Code:-
GetHospNames.cs
public class GetHospNames
{
public string HospID { get; set; }
public string HospName { get; set; }
public GetHospNames(string HospID, string HospName)
{
this.HospID = HospID;
this.HospName = HospName;
//this.HospLogo = HospLogo;
}
}
ContListViewHospNameClass.cs
using System.Collections.Generic;
using Android.App;
using Android.Views;
using Android.Widget;
using System;
using Android.Graphics;
using Android.Graphics.Drawables;
using System.IO;
using Android.Content;
using Java.Lang;
using Android.Text;
using Java.Util;
using Oject = Java.Lang.Object;
namespace HSAPP
{
public class ContListViewHospNameClass : BaseAdapter<GetHospNames>, IFilterable
{
public List<GetHospNames> objList;
Activity objActivity;
List<GetHospNames> filterList;
public ContListViewHospNameClass(Activity objMyAct, List<GetHospNames> objMyList) : base()
{
this.objActivity = objMyAct;
objList = objMyList;
this.filterList = objList;
Filter = new CustomFilter(this);
}
public override GetHospNames this[int position]
{
get
{
return objList[position];
}
}
public override int Count
{
get
{
return objList.Count;
}
}
public Filter Filter { get; set; }
public override void NotifyDataSetChanged()
{
base.NotifyDataSetChanged();
}
//This is Inner Class
public class CustomFilter : Filter
{
ContListViewHospNameClass CustomAdapter;
public CustomFilter(ContListViewHospNameClass adapter) : base()
{
this.CustomAdapter = adapter;
}
protected override FilterResults PerformFiltering(ICharSequence constraint)
{
FilterResults result = new FilterResults();
if (constraint != null && constraint.Length() > 0)
{
//Contraint To Upper
List<GetHospNames> filter = new List<GetHospNames>();
foreach (GetHospNames name in CustomAdapter.objList)
{
if (name.HospName.ToUpper().Contains(constraint.ToString().ToUpper()))
{
filter.Add(name);
}
}
Oject[] Name;
Name = new Oject[filter.Count];
for (int i = 0; i < filter.Count; i++)
{
Name[i] = filter[i].HospName.ToString();
}
result.Count = filter.Count;
result.Values = Name;
}
return result;
}
protected override void PublishResults(ICharSequence constraint, Filter.FilterResults result)
{
List<GetHospNames> filteredList = new List<GetHospNames>();
for (int i = 0; i < ((Oject[])result.Values).Length; i++)
{
filteredList.Add((Oject[])result.Values[i]);//Here Is An Error *****Cannot apply indexing with [] to an expression of type 'Object'****
}
CustomAdapter.objList = filteredList;
CustomAdapter.NotifyDataSetChanged();
}
}
public override long GetItemId(int position)
{
return position;
}
public Bitmap getBitmap(byte[] getByte)
{
if (getByte.Length != 0)
{
return BitmapFactory.DecodeByteArray(getByte, 0, getByte.Length);
}
else
{
return null;
}
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
var item = objList[position];
if (convertView == null)
{
convertView = objActivity.LayoutInflater.Inflate(Resource.Layout.ContListViewHospName, null);
}
convertView.FindViewById<TextView>(Resource.Id.tvHospID).Text = item.HospID;
convertView.FindViewById<TextView>(Resource.Id.tvHospName).Text = item.HospName;
return convertView;
}
}
public static class ObjectTypeHelper
{
public static T Cast<T>(this Java.Lang.Object obj) where T : class
{
var propertyInfo = obj.GetType().GetProperty("Instance");
return propertyInfo == null ? null : propertyInfo.GetValue(obj, null) as T;
}
}
}
This is my MainActivity Code
private void BindControl_BindHospCompleted(object sender, BindControl.BindHospCompletedEventArgs e)
{
jsonValue = e.Result.ToString();
try
{
if (jsonValue == null)
{
Toast.MakeText(this, "No Data For Bind", ToastLength.Long).Show();
return;
}
JArrayValue = JArray.Parse(jsonValue);
list = new List<GetHospNames>();
int count = 0;
while (count < JArrayValue.Count)
{
GetHospNames getHospName = new GetHospNames(JArrayValue[count]["HospID"].ToString(), JArrayValue[count]["HospName"].ToString());
list.Add(getHospName);
count++;
}
if (count == 0)
{
Toast.MakeText(this, "No List Of Hospitals", ToastLength.Long).Show();
}
adapter = new ContListViewHospNameClass(this, list);
listView.Adapter = adapter;
search.QueryTextChange += (s, e) =>
{
adapter.Filter.InvokeFilter(e.NewText);
};
listView.ItemClick += ListView_ItemClick;
pBar.Dismiss();
}
catch (Java.Lang.Exception ex)
{
pBar.Dismiss();
//Toast.MakeText(this, ex.ToString(), ToastLength.Long).Show();
Finish();
Intent intent = new Intent(this, typeof(ChkIntConnActivity));
StartActivity(intent);
}
}
Please Help...Thank You

How to Fix Getting CS1518: Expected class, delegate, enum, interface, or struct error

How to Fix Getting CS1518: Expected class, delegate, enum, interface, or struct error
{ ImplementsSystem.ComponentModel.INotifyPropertyChanging.PropertyChanging;
ImplementsSystem.ComponentModel.INotifyPropertyChanged.PropertyChanged;
public event PropertyChangingEventHandler PropertyChanging;
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void SendPropertyChanging();
}
{
if (((this.PropertyChangingEvent == null) == false)) {
if (PropertyChanging != null) {
RaiseEventPropertyChanging(this, emptyChangingEventArgs);
}
}
}
protected virtual void SendPropertyChanged(String propertyName) {
if (((this;PropertyChangedEvent == null)
== false)) {
RaiseEventPropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
}

Create a custom Spinner

I am trying to customize the MvxSpinner to add some additional controls, here is my code:
public class ChamSpinner : LinearLayout
{
public Spinner Spinner{ get; private set; }
public EventHandler<AdapterView.ItemSelectedEventArgs> ItemSelected;
public ChamSpinner (Context context, IAttributeSet attrs) : this (context, attrs, new ChamSpinnerAdapter (context))
{
}
public ChamSpinner (Context context, IAttributeSet attrs, IMvxAdapter adapter) : base (context, attrs)
{
((Activity)Context).LayoutInflater.Inflate (Resource.Layout.ChamSpinnerLayout, this);
Spinner = FindViewById<Spinner> (Resource.Id.ChamSpinnerSpinner);
int itemTemplateId = MvxAttributeHelpers.ReadListItemTemplateId (context, attrs);
int dropDownItemTemplateId = MvxAttributeHelpers.ReadDropDownListItemTemplateId (context, attrs);
adapter.ItemTemplateId = itemTemplateId;
adapter.DropDownItemTemplateId = dropDownItemTemplateId;
Adapter = adapter;
SetupHandleItemSelected ();
}
public new IMvxAdapter Adapter
{
get { return Spinner.Adapter as IMvxAdapter; }
set
{
var existing = Adapter;
if (existing == value)
return;
if (existing != null && value != null)
{
value.ItemsSource = existing.ItemsSource;
value.ItemTemplateId = existing.ItemTemplateId;
}
Spinner.Adapter = value;
}
}
[MvxSetToNullAfterBinding]
public IEnumerable ItemsSource
{
get
{
return Adapter.ItemsSource;
}
set
{
Adapter.ItemsSource = value;
}
}
public int ItemTemplateId
{
get { return Adapter.ItemTemplateId; }
set { Adapter.ItemTemplateId = value; }
}
public int DropDownItemTemplateId
{
get { return Adapter.DropDownItemTemplateId; }
set { Adapter.DropDownItemTemplateId = value; }
}
public ICommand HandleItemSelected { get; set; }
private void SetupHandleItemSelected ()
{
Spinner.ItemSelected += (sender, args) =>
{
var position = args.Position;
HandleSelected (position);
if (ItemSelected != null)
ItemSelected (sender, args);
};
}
protected virtual void HandleSelected (int position)
{
var item = Adapter.GetRawItem (position);
if (this.HandleItemSelected == null
|| item == null
|| !this.HandleItemSelected.CanExecute (item))
return;
this.HandleItemSelected.Execute (item);
}
}
And I am using it like this:
<cross.android.ChamSpinner
android:layout_width="fill_parent"
android:layout_height="wrap_content"
local:MvxDropDownItemTemplate="#layout/myspinneritemdropdown"
local:MvxItemTemplate="#layout/myspinneritem"
local:MvxBind="ItemsSource MyItemsSource; SelectedItem MyItem; Mode TwoWay" />
The spinner is always empty, I tried to add a custom binding on ItemsSource property but the result stilll the same.
How can I do to show my items in my spinner?
Thank you in advance.
I think using BindingInflate instead of Inflate should fix it or even points you in the right direction. https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross.Binding.Droid/BindingContext/IMvxAndroidBindingContext.cs
((IMvxBindingContextOwner)Context).BindingInflate(Resource.Layout.ChamSpinnerLayout, this);
I found this error in my log
MvxBind:Error: 32,12 View type not found - cross.android.ChamSpinner
My custom control is in another assembly so I added it to MvvmCross View assemblies is my Setup class like this
protected override IList<Assembly> AndroidViewAssemblies
{
get
{
var assemblies = base.AndroidViewAssemblies;
assemblies.Add(typeof(ChamSpinner).Assembly);
return assemblies;
}
}
Thank you Stuart for your advices and for your great Framework.

Resources