Piszą swój cykl postów o WPF a w szczególności wpis, o DataBindingu pominąłem jeden ciekawy rodzaj bindingu o którym chciałbym dziś wspomnieć.
Załóżmy, że mamy UI, który wyświetla jakieś elementy, które pobierane są z WebService’u. Oczywiście strzał do WebService’u (® by Marcin Najder) jest kosztowny jeśli chodzi o czas a UI nie chcemy blokować. Możemy wykorzystać w tym celu PriorityBinding. Jak?

Załóżmy, że nasza klasa dostępu do danych wygląda następująco:

public class DataAccess
{
    public List<string> WebService
    {
        get
        {
            Thread.Sleep(5000);
            return new List<string> { “1 from WebService”, “2 from WebService”, “3 from WebService” };
        }
    }
    public List<string> Cache
    {
        get
        {
            Thread.Sleep(1500);
            return new List<string> { “1 from cache”, “2 from cache” };
        }
    }
    public List<string> Instant
    {
        get
        {
            return new List<string> { “Loading. Please wait…” };
        }
    }
}

Mamy zatem 3 źródła różniące się szybkością dostępu. Instant nie zawiera żadnych aktualnych danych, cache ma przechowywane lokalnie dane, które oczywiście mogą być nie do końca prawidłowe, natomiast WebService zwraca nam najnowsze dane. Jak napisać binding, aby nasz UI aktualizował się w miarę jak będziemy otrzymywać dane tj. aby od razu wypisał to co zwróci Instant a później gdy otrzyma dane z Cache lub z WebService zaktualizował się automatycznie? <PriorityBinding.

<ListBox>
    <ListBox.ItemsSource>
        <PriorityBinding>
            <Binding Path=”WebService” IsAsync=”True” />
            <Binding Path=”Cache” IsAsync=”True” />
            <Binding Path=”Instant” />
        PriorityBinding>
    ListBox.ItemsSource>
ListBox>

Oczywiście zakładając, że DataContext jest ustawiony na naszą klasę DataAccess. Jak to zadziała? Kolejność wpisów ustala priorytet. Im wyżej tym ważniejsze i prawdopodobnie bardziej czasochłonne wykonanie funkcji. Im niżej tym powinno ono być mniej ważne i szybsze. Dzięki ustawieniu parametru IsAsync na true, wywołania czasochłonne nie zostaną wywołane w wątku UI, blokując go jednocześnie a w wątku BackgroundWorker’a.
Efekt finalny…

Nice 🙂
Miłego kodowania!