Get input in Angular

Published 4/6/2020 by Christian

To atrive 2-way binding i Angular, declare a var in the component.ts file:

public customerName: string;

And bind to it the .html file:

<input [(ngModel)]="customerName" [ngModelOptions]="{standalone: true}">

I just getting started with some Anuglar web development, so mostly for my own benefit, this will be an ongoing collection of notes, urls ect. I'll update as I get deeper into creating Angular web apps. 

CLI Overview and Command Reference

In short:

# setup

npm install @angular/cli --global

ng --version

# bootstrap

ng new demoApp --minimal --routing --style=less --dry-run

cd demoApp

# build

ng build --prod

cd dist/demoAppp

# serve

npm install serve --global

serve

# cleanup

npm install rimraf --global 

rimraf demoApp

 

Install git:


Hi there,

 

Although this post is very informative, it didn’t quite fulfill my needs.

I needed to start an asynchronous method, lazy loading some data, when a property bound to a WPF control was updated.

This is what I came up with:

 

public void UpdateInformation(string propertyValue)
{
	System.Windows.Threading.Dispatcher.CurrentDispatcher.Invoke(new Action(async () =>
	{
		_cancellationTokens.ForEach(c => c.Cancel());
		using (CancellationTokenSource cancellationToken = new CancellationTokenSource())
		{
			try
			{
				_cancellationTokens.Add(cancellationToken);
				var dataResponse = await service.LoadData(propertyValue, cancellationToken);
				...
			}
			finally
			{
				_cancellationTokens.Remove(cancellationToken);
			}
		}
	}));
}

As always, feel free to ask or comment.


Whats new in C# 8.0

Published 3/19/2019 by Christian
Tags:

Well:

https://www.youtube.com/watch?v=VdC0aoa7ung

Neat new stuff


Convert XML String to Object

Published 3/12/2019 by Christian

Just a quick link this time:

 

https://stackoverflow.com/questions/3187444/convert-xml-string-to-object

 

Required Visual Studio 2012+ with .Net Framework >= 4.5 as project target

Copy content of your XML file to clipboard

Add to your solution new, empty class file (Shift+Alt+C)

Open that file and in menu click Edit > Paste special > Paste XML As Classes

And that's it!

Thanks to Damian Drygiel for a great writeup


Cancel an async task

Published 12/20/2018 by Christian in Code
Tags: , , ,

So, I wanted to do asynchronously database search that could take a long time. But if the user refine her search criteria, the async should restart, and whatever already found records be disregarded.

Using the following Microsoft article as a template, this is what I came up with as a proof of concept.

 https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/cancel-an-async-task-or-a-list-of-tasks

 

This WPF program has 3 buttons. 

Start - will cancel all already started jobs, waits for 5 sec. and then download some content from a msdn site.

Cancel All - will simply cancel all started jobs.

Clear - will cancel all started jobs, and clear any messages.

 

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows;

// Add a using directive and a reference for System.Net.Http.
using System.Net.Http;

// Add the following using directive for System.Threading.
using System.Threading;

namespace CancelATask
{
    public partial class MainWindow : Window
    {
        // ***Declare a System.Threading.CancellationTokenSource.
        List<CancellationTokenSource> cts = new List<CancellationTokenSource>();

        public MainWindow()
        {
            InitializeComponent();
        }


        private async void startButton_Click(object sender, RoutedEventArgs e)
        {
            cts?.ForEach(c => c.Cancel());
            // ***Instantiate the CancellationTokenSource.
            using (CancellationTokenSource c = new CancellationTokenSource())
            {
                cts.Add(c);

                try
                {
                    // ***Send a token to carry the message if cancellation is requested.
                    int contentLength = await AccessTheWebAsync(c.Token);
                    resultsTextBox.Text += $"\r\nLength of the downloaded string: {contentLength}.\r\n";
                }
                // *** If cancellation is requested, an OperationCanceledException results.
                catch (OperationCanceledException)
                {
                    resultsTextBox.Text += $"\r\nDownload canceled. Current no of jobs: {cts.Count}\r\n";
                }
                catch (Exception)
                {
                    resultsTextBox.Text += "\r\nDownload failed.\r\n";
                }
                cts.Remove(c);
            }
        }


        // ***Add an event handler for the Cancel button.
        private void cancelButton_Click(object sender, RoutedEventArgs e)
        {
            cts?.ForEach(c => c.Cancel());
        }

        private void clearButton_Click(object sender, RoutedEventArgs e)
        {
            cts?.ForEach(c => c.Cancel());
            resultsTextBox.Clear();
        }

        // ***Provide a parameter for the CancellationToken.
        async Task<int> AccessTheWebAsync(CancellationToken c)
        {
            HttpClient client = new HttpClient();

            resultsTextBox.Text += "Waiting for download to commence.\r\n";

            // You might need to slow things down to have a chance to cancel.
            await Task.Delay(5000, c);

            resultsTextBox.Text += "Commencing to download.\r\n";
            // GetAsync returns a Task<HttpResponseMessage>. 
            // ***The c argument carries the message if the Cancel button is chosen.
            HttpResponseMessage response = await client.GetAsync("http://msdn.microsoft.com/en-us/library/dd470362.aspx", c);

            // Retrieve the website contents from the HttpResponseMessage.
            byte[] urlContents = await response.Content.ReadAsByteArrayAsync();

            // The result of the method is the length of the downloaded web site.
            return urlContents.Length;
        }
    }

    // Output for a successful download:

    // Ready to download.

    // Length of the downloaded string: 158125.


    // Or, if you cancel:

    // Ready to download.

    // Download canceled.
}

 

As always feel free to ask or comment.


Force invalidate XAML bindings

Published 8/31/2018 by Christian

To force the System.Windows.Input.CommandManager to raise the System.Windows.Input.CommandManager.RequerySuggested event, call:

System.Windows.Input.CommandManager.InvalidateRequerySuggested();

As always feel to ask or comment.


This one gave me some headache, but as always, looking back the solution is pretty obvious.

Using WPF, in a MVVM design pattern, I have a ListView bound to a ObservableCollection. Straight forward senario.

XAML:

<ListView Name="lvCustomerSearchResults" ItemsSource="{Binding CustomerSearchResults}" SelectedItem="{Binding SelectedCustomer}" ...

 

ViewModel:

 

public async Task<AOTaskResult<List<CustomerSearchResultEntity>>> SearchCustomers(string cvrNo, Statuses? status = null, DateTime? fromDate = null, DateTime? toDate = null)
{
    return await Task.Run(() =>
    {
        AOTaskResult<List<CustomerSearchResultEntity>> result = new AOTaskResult<List<CustomerSearchResultEntity>>();
        try
        {
            result.Response = _repository.LstCustomers(cvrNo, status, fromDate, toDate, out List<NezCusCustomerDTO> dtos);
            if (result.Response.Success)
            {
                result.Result = dtos.Select(d => LocalMapping.ToCustomerSearchResultEntity(d)).ToList();
            }
        }
        catch (Exception ex) { CheckTaskException(ex); }
        return result;
    });
}

 

Trouble is when I click an item in the ListWiew I get a “Must create DependencySource on same Thread as the DependencyObject”-exception. It turns out that the reason I get this exception is that I created the items in the ObservableCollection on another thread than the main-thread. So, obviously, the solution is to create the the ObservableCollection items on the main-thread:

public async Task<AOTaskResult<List<CustomerSearchResultEntity>>> SearchCustomers(string cvrNo, Statuses? status = null, DateTime? fromDate = null, DateTime? toDate = null)
{
    AOTaskResult<List<CustomerSearchResultEntity>> result = new AOTaskResult<List<CustomerSearchResultEntity>>();
    List<NezCusCustomerDTO> dtos = null;

    await Task.Run(() =>
    {
        try
        {
            Busy = true;
            result.Response = _repository.LstCustomers(cvrNo, status, fromDate, toDate, out dtos);

            Busy = false;
        }
        catch (Exception ex) { CheckTaskException(ex); }
    });
    if (dtos != null && result.Response.Success)
    {
        result.Result = dtos.Select(d => LocalMapping.ToCustomerSearchResultEntity(d)).ToList();
    }
    return result;
}

 

 IMO, the code is not as clean ... but it works :-)

 

As always feel to ask or comment.


XAML TabIndex dosen't work.

Published 11/3/2017 by Christian

I've just been struggling with getting the TabIndex on XAML controls to work for an hour. Getting quite frustrated I can asure you. 

Anyway - after searching the o' Google to no awail, it occured to me that maybe Visual Studio needed to completely rebuild the app to kind of re-tab-index-ing the controls, so I ended up deleting the 'obj' and 'bin' folders - and Voilà!- all of a sudden all my TabIndex's worked.

 

As always feel to ask or comment.


Replaceing the default difference/merge tool in Visual Studio with WinMerge is fairly easy, but I keep forgetting, so I figured I'd do a quick write-up.

Subversion (SVN)

After installing WinMerge, in Visual Studio, go to 

Tools -> Options -> Source Control and depending on your Source Control selection (in the case here Subversion) look for a 'Tools' menu (with Subversion its under Subversion User Tools):

If you are using Subversion/TortoiseSVN you can simply select WinMerge from the 'External Diff Tool' and 'External Merge Tool' combo boxes:

 

As always feel to ask or comment.