Prosty skaner portów z wykorzystaniem MVVM Light – Dispatcher helper

Ostatnimi czas dużo bawię się WPF, a dokładniej wzorcem projektowym MVVM. Postanowiłem napisać projekt, który własnie wykorzystuje wspominane wcześniej technologie. A w szczególności biblioteki wspomagające pisanie programów zgodnych z MVVM. Chodzi mi o MVVM Light

Założenia techniczne projektu to:

1. Napisany w WPF z wykorzystaniem wzorca MVVM.
2. Użycie bibliotek MVVM light
3. Wykorzystanie możliwe jak największej ilości funkcji MVVM light

Założenia projektu:

1. Prosty skaner portów TCP (bardziej chodzi o użycie Dispatcher)
2. Użycie Dispatchera (wielowątkowość) w przypadku MVVM light klasy DispatcherHelper
3. Walidacja wprowadzanych danych (TO DO)
4. Być może coś jeszcze…

Źródła projektu SkanerMVVM

Opis kroków.

1. Na początek dodajemy paczkę przy pomocy Nugeta – nazwa paczki MVVM Light

2. W głównym oknie ręcznie bindujemy DataContext do ViewModelLocatora


3. Bindujemy komendę Scan w pliku xaml (a) oraz definiujemy komendę (b) oraz jej metodę (c) ScanExecute.

(a)

<button></button>

(b)

public MainViewModel()
        {
            Scan = new RelayCommand(() => ScanExecute(), () => true);
        }

(c)

private object ScanExecute()
        {
            Scaner scanner = new Scaner(Host);
            scanner.Scan();
            ScanedPortList = scanner.ScanedPorts;

            return ScanedPortList;
        }

4. Tworzymy klasę Skaner. Nie będę się nad nią zbytnio tutaj rozwodził. Jest to poprostu klasa skanująca porty po petli foreach w róznych wątkach. Prosze tutaj jednak zwrócić uwagę sposób użycia DispatcherHelpera.

private void CallBack(IAsyncResult result)
        {
            using (TcpClient client = (TcpClient)result.AsyncState)
            {
                var connectedPort = ((IPEndPoint)client.Client.RemoteEndPoint).Port;

                if (client.Connected)
                {
                    client.EndConnect(result);
                    DispatcherHelper.CheckBeginInvokeOnUI(
                    () => { ScanedPorts.Add("Port: " + connectedPort + " is open"); });
                }
                else
                {
                    DispatcherHelper.CheckBeginInvokeOnUI(
                    () => { ScanedPorts.Add("Port: " + connectedPort + " is close"); });
                }
            }
        }

Aby móc korzystać z możliwości aktualizacji Twojego UI z innych wątków musisz w klasie aplikacji go najpierw zainicjować.

public partial class App : Application
    {
        static App()
        {
            DispatcherHelper.Initialize();
        }
    }

W następnym wpisie o walidacji wprowadzanych danych.