Categories
.NET Programming

Using .NET COM component in ASP (classic) application

Recently I had to reinstall an old ASP (classic, not ASP.NET) application which used COM components which were made in .NET.
Unfortunately the components could not be instantiated (via Server.CreateObject) and I would always get an error 80131700.
The solution was that you need to enable the .NET CLR on your Application Pool even though your are not normally using the .NET runtime.
Hopefully this helps someone else who has the same problem.

Categories
.NET Programming Xamarin Forms

Using accent color as ListView selected cell color (Xamarin Forms Android)

The Xamarin Forms ListView control displays a list of items and can also indicate currently selected item. However, if you modified the base colors of your Android application the background color of the currently selected item is not matching the Android accent color.
This can be achieved by a custom cell renderer which will set the background color of the list view selected Cell to the accent color in case that the Cell is selected.

Here is the code:

public class CustomCellRenderer : ViewCellRenderer
{

    private Dictionary _cells = new Dictionary();

    protected override global::Android.Views.View GetCellCore(Cell item, global::Android.Views.View convertView, ViewGroup parent, Context context)
    {
        // Generate the View for the cell
        var view = base.GetCellCore(item, convertView, parent, context);
        bool isSelected;

        // Determine if the cell is selected by checking if the owner ListView SelectedItem property matches the cell BindingContext
        // Unfortunately although the cell internally tracks if it is selected or not, we can not access that information because its private
        Xamarin.Forms.ListView lv = item.Parent as Xamarin.Forms.ListView;
        if (lv != null)
            isSelected = lv.SelectedItem == item.BindingContext;
        else
            isSelected = false;

        // Store the current cell selection status
        _cells[item] = (view, isSelected);

        // Set the color of the underlying view immediately
        SetColor(view, isSelected);
        return view;
    }

    protected override void OnCellPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        base.OnCellPropertyChanged(sender, e);
        if(e.PropertyName == "IsSelected")
        {
            // Unfortunately although the cell internally tracks if it is selected or not, we can not access that information because its private
            // However we can catch the firing of the event when the cell IsSelected property changes
            var item = _cells[(Cell)sender];
            // Set the color of the underlying view
            SetColor(item.view, !item.selected);
            // Invert the selected flag
            _cells[(Cell)sender] = (item.view, !item.selected);
        }
    }

    private void SetColor(global::Android.Views.View view, bool isSelected)
    {
        global::Android.Graphics.Color backgroundColor;
        if (isSelected)
        {
            // Use the accent color if the cell is selected
            backgroundColor = new global::Android.Graphics.Color(global::Android.Support.V4.Content.ContextCompat.GetColor(view.Context, Resource.Color.colorAccent));
        }
        else
        {
            backgroundColor = global::Android.Graphics.Color.Transparent;
        }
        view.SetBackgroundColor(backgroundColor);
    }

}
Categories
.NET Core Xamarin Forms

InputTransparent vs IsEnabled in Xamarin Forms

One of the problems in Xamarin Forms is that it is not possible to setup the text colors of disabled elements (elements where IsEnabled property is set to false).
However you do not need to set the IsEnabled property to disable it, there is an alternative property called InputTransparent.
Setting InputTransparent to true (by default it is false) will effectively disable the control by not allowing the user to interact with it.

The only drawback is that there is no visual indicator that the control is disabled, however this can be achieved by manually changing the text or background color of the control when it is disabled in this way.

Categories
.NET .NET Core Programming

TIL: Double.Equals works with Double.NaN values

The .NET standard defines that the double value of NaN (Double.NaN) will never be equal to any other Double value, including itself.
In other words:

double first = Double.NaN;
double second = Double.NaN;
bool equal = first == second; // false;

However this does not hold for Double.Equals. Double.Equals checks for object 'Identity' and not object 'Equality'.

double first = Double.NaN;
double second = Double.NaN;
bool equal = first.Equals(second); // true;

This is in general a nice thing if you have a generic methods which rely on object equality. Object.Equals will work even for Double and Single types.

Categories
.NET Core

Listing all routes in ASP.NET Core application

It is pretty simple to list all routes configured in your ASP.NET Core application:

  1. Add Microsoft.AspNetCore.Mvc.Infrastructure.IActionDescriptorCollectionProvider parameter to your Startup.Configure method.
  2. If you have not done so already also add the ILogger<Startup> parameter to Startup.Configure as well
  3. Loop through all action descriptor items in the IActionDescriptorCollectionProvider and display the log information

Here is an example Startup method:

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILogger log, Microsoft.AspNetCore.Mvc.Infrastructure.IActionDescriptorCollectionProvider actionProvider)
    {
        log.Log(LogLevel.Information, "Configuring application ...");

        /// .... configuration

        app.UseMvc();

        log.Log(LogLevel.Information, "Available routes:");
        var routes = actionProvider.ActionDescriptors.Items.Where(x => x.AttributeRouteInfo != null);
        foreach(var route in routes)
        {
            log.Log(LogLevel.Debug, $"{route.AttributeRouteInfo.Template}");
        }

        log.Log(LogLevel.Information, "... finished configuring application");
    }