Aracılığıyla paylaş


RelayCommand özniteliği

türü RelayCommand , açıklamalı yöntemler için geçiş komutu özellikleri oluşturulmasına izin veren bir özniteliktir. Amacı, bir görünüm modelinde özel yöntemleri sarmalayan komutları tanımlamak için gereken ortak değeri tamamen ortadan kaldırmaktır.

Not

Çalışmak için, açıklamalı yöntemlerin kısmi bir sınıfta olması gerekir. Tür iç içe yerleştirilmişse bildirim söz dizimi ağacındaki tüm türler de kısmi olarak ek açıklama eklenmelidir. Oluşturucu istenen komutla bu tür için farklı bir kısmi bildirim oluşturamayacağından, bunu yapmamak derleme hatalarına neden olur.

Platform API'leri:RelayCommand, ICommand, IRelayCommand, IRelayCommand<T>, IAsyncRelayCommand, IAsyncRelayCommand<T>, TaskCancellationToken

Nasıl çalışır?

özniteliği, RelayCommand kısmi türde bir yönteme açıklama eklemek için kullanılabilir, örneğin:

[RelayCommand]
private void GreetUser()
{
    Console.WriteLine("Hello!");
}

Ve şuna benzer bir komut oluşturur:

private RelayCommand? greetUserCommand;

public IRelayCommand GreetUserCommand => greetUserCommand ??= new RelayCommand(GreetUser);

Not

Oluşturulan komutun adı, yöntem adına göre oluşturulur. Oluşturucu yöntem adını kullanacak ve sonuna "Command" ekleyecek ve varsa "Açık" ön ekini çıkaracaktır. Ayrıca, zaman uyumsuz yöntemler için "Command" uygulamadan önce "Async" soneki de çıkarılır.

Komut parametreleri

özniteliği, [RelayCommand] bir parametre ile yöntemler için komut oluşturmayı destekler. Bu durumda, aynı türdeki bir parametreyi kabul ederek oluşturulan komutu otomatik olarak bir IRelayCommand<T> olarak değiştirir:

[RelayCommand]
private void GreetUser(User user)
{
    Console.WriteLine($"Hello {user.Name}!");
}

Bu, aşağıdaki kodun oluşturulmasına neden olur:

private RelayCommand<User>? greetUserCommand;

public IRelayCommand<User> GreetUserCommand => greetUserCommand ??= new RelayCommand<User>(GreetUser);

Sonuçta elde edilen komut, bağımsız değişkenin türünü bağımsız değişkeni olarak otomatik olarak kullanır.

Zaman uyumsuz komutlar

[RelayCommand] komutu, ve IAsyncRelayCommand<T> arabirimleri aracılığıyla zaman uyumsuz yöntemleri sarmalama işlemini IAsyncRelayCommand de destekler. Bu, bir yöntem bir tür döndürdüğünde Task otomatik olarak işlenir. Örneğin:

[RelayCommand]
private async Task GreetUserAsync()
{
    User user = await userService.GetCurrentUserAsync();

    Console.WriteLine($"Hello {user.Name}!");
}

Bu, aşağıdaki kodla sonuçlanır:

private AsyncRelayCommand? greetUserCommand;

public IAsyncRelayCommand GreetUserCommand => greetUserCommand ??= new AsyncRelayCommand(GreetUserAsync);

Yöntem bir parametre alırsa, sonuçta elde edilen komut da genel olacaktır.

yönteminde bir olduğunda CancellationTokenözel bir durum vardır, bu durum iptali etkinleştirmek için komutuna yayılır. Yani, aşağıdaki gibi bir yöntem:

[RelayCommand]
private async Task GreetUserAsync(CancellationToken token)
{
    try
    {
        User user = await userService.GetCurrentUserAsync(token);

        Console.WriteLine($"Hello {user.Name}!");
    }
    catch (OperationCanceledException)
    {
    }
}

Oluşturulan komutun sarmalanan yönteme bir belirteç geçirmesine neden olur. Bu, tüketicilerin yalnızca bu belirteci sinyal olarak çağırmasına IAsyncRelayCommand.Cancel ve bekleyen işlemlerin doğru şekilde durdurulmasına izin vermesine olanak tanır.

Komutları etkinleştirme ve devre dışı bırakma

Komutları devre dışı bırakmak ve daha sonra durumlarını geçersiz kılıp yürütülemeyeceklerini yeniden denetlemelerini sağlamak genellikle yararlıdır. Bunu desteklemek için özniteliği, bir komutun RelayCommandCanExecute yürütülebilir olup olmadığını değerlendirmek için kullanılacak bir hedef özelliği veya yöntemi belirtmek için kullanılabilen özelliğini kullanıma sunar:

[RelayCommand(CanExecute = nameof(CanGreetUser))]
private void GreetUser(User? user)
{
    Console.WriteLine($"Hello {user!.Name}!");
}

private bool CanGreetUser(User? user)
{
    return user is not null;
}

Bu şekilde, CanGreetUser düğme kullanıcı arabirimine ilk bağlandığında (örn. bir düğmeye) çağrılır ve ardından komutta her IRelayCommand.NotifyCanExecuteChanged çağrıldığında yeniden çağrılır.

Örneğin, bir komut durumunu denetlemek için bir özelliğe bu şekilde bağlanabilir:

[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(GreetUserCommand))]
private User? selectedUser;
<!-- Note: this example uses traditional XAML binding syntax -->
<Button
    Content="Greet user"
    Command="{Binding GreetUserCommand}"
    CommandParameter="{Binding SelectedUser}"/>

Bu örnekte, oluşturulan SelectedUser özellik değeri her değiştiğinde yöntemini çağıracaktır GreetUserCommand.NotifyCanExecuteChanged() . Kullanıcı arabirimi için GreetUserCommandbir Button denetim bağlaması vardır, yani olayı her CanExecuteChanged tetiklendiğinde yöntemini yeniden çağırırCanExecute. Bu, sarmalanan CanGreetUser yöntemin değerlendirilmesine neden olur ve bu da giriş User örneğinin (kullanıcı arabiriminde özelliğine SelectedUsernull bağlı) olup olmadığına bağlı olarak düğmenin yeni durumunu döndürür. Bu, her SelectedUser değiştirildiğinde bu GreetUserCommand özelliğin bir değere sahip olup olmadığına bağlı olarak etkinleştirileceği veya etkinleştirilmeyeceği anlamına gelir. Bu, bu senaryoda istenen davranıştır.

Not

Yöntemin veya özelliğin dönüş değeri değiştiğinde CanExecute komut otomatik olarak fark edilmeyecektir. Komutu geçersiz kılıp bağlı CanExecute yöntemin yeniden değerlendirilmesini istemek, ardından komuta bağlı denetimin görsel durumunu güncelleştirmek için geliştiricinin çağrısına IRelayCommand.NotifyCanExecuteChanged bağlıdır.

Eşzamanlı yürütmeleri işleme

Bir komut zaman uyumsuz olduğunda, eşzamanlı yürütmelere izin verilip verilmeyeceğine karar verecek şekilde yapılandırılabilir. özniteliği kullanılırken RelayCommand , bu özellik aracılığıyla AllowConcurrentExecutions ayarlanabilir. varsayılan değeridir false; başka bir deyişle, bir yürütme bekleyene kadar komutun durumunu devre dışı olarak işaret edeceği anlamına gelir. Bunun yerine olarak ayarlanırsa true, herhangi bir sayıda eşzamanlı çağrı kuyruğa alınabilir.

Bir komut iptal belirteci kabul ederse eşzamanlı yürütme istenirse bir belirtecin de iptal edileceğini unutmayın. Temel fark, eşzamanlı yürütmelere izin verilirse komutun etkin kalması ve öncekinin gerçekten tamamlanmasını beklemeden yeni bir istenen yürütme başlatmasıdır.

Zaman uyumsuz özel durumları işleme

Zaman uyumsuz geçiş komutlarının özel durumları işlemesinin iki farklı yolu vardır:

  • Await ve rethrow (varsayılan): komut bir çağrının tamamlanmasını beklediğinde, tüm özel durumlar doğal olarak aynı eşitleme bağlamında oluşturulur. Bu genellikle, oluşan özel durumların yalnızca uygulamayı kilitleyeceği anlamına gelir; bu, zaman uyumlu komutlarla tutarlı bir davranıştır (oluşan özel durumlar da uygulamayı kilitler).
  • Görev zamanlayıcıya akış özel durumları: Bir komut özel durumları görev zamanlayıcıya akıtacak şekilde yapılandırıldıysa, oluşturulan özel durumlar uygulamayı kilitlenmez, bunun yerine hem kullanıma sunulan IAsyncRelayCommand.ExecutionTask aracılığıyla hem de öğesine kadar TaskScheduler.UnobservedTaskExceptionkabarcıklama yoluyla kullanılabilir hale gelir. Bu, daha gelişmiş senaryolara olanak tanır (kullanıcı arabirimi bileşenlerinin göreve bağlanması ve işlemin sonucuna göre farklı sonuçlar görüntülemesi gibi), ancak doğru şekilde kullanılması daha karmaşıktır.

Varsayılan davranış, özel durumları bekleyen ve yeniden oluşturan komutlara sahip olmaktır. Bu, özelliği aracılığıyla FlowExceptionsToTaskScheduler yapılandırılabilir:

[RelayCommand(FlowExceptionsToTaskScheduler = true)]
private async Task GreetUserAsync(CancellationToken token)
{
    User user = await userService.GetCurrentUserAsync(token);

    Console.WriteLine($"Hello {user.Name}!");
}

Bu durumda, try/catch özel durumlar artık uygulamayı kilitlenmeyeceği için gerekli değildir. Bunun diğer ilgisiz özel durumların otomatik olarak yeniden yıkılmamasına da neden olacağını unutmayın. Bu nedenle her bir senaryoya nasıl yaklaşacağınız ve kodun geri kalanını uygun şekilde nasıl yapılandıracağınız konusunda dikkatli bir karar vermeniz gerekir.

Zaman uyumsuz işlemler için komutları iptal etme

Zaman uyumsuz komutların son seçeneklerinden biri, bir iptal komutunun oluşturulmasını isteme özelliğidir. Bu, bir ICommand işlemin iptalini istemek için kullanılabilecek bir zaman uyumsuz geçiş komutunu sarmalama işlemidir. Bu komut, belirli bir zamanda kullanılıp kullanılamayacağını yansıtmak için durumunu otomatik olarak sinyalleyecektir. Örneğin, bağlı komut yürütülmezse, durumunu yürütülebilir değil olarak bildirir. Bu, aşağıdaki gibi kullanılabilir:

[RelayCommand(IncludeCancelCommand = true)]
private async Task DoWorkAsync(CancellationToken token)
{
    // Do some long running work...
}

Bu, bir DoWorkCancelCommand özelliğin de oluşturulmasına neden olur. Bu, kullanıcıların bekleyen zaman uyumsuz işlemleri kolayca iptal etmesine olanak sağlamak için başka bir kullanıcı arabirimi bileşenine bağlanabilir.

Özel öznitelikler ekleme

Gözlemlenebilir özelliklerde olduğu gibi oluşturucu da RelayCommand oluşturulan özellikler için özel öznitelikler için destek içerir. Bundan yararlanmak için öznitelik listelerindeki hedefi açıklamalı yöntemler üzerinden kullanabilirsiniz [property: ] ve MVVM Araç Seti bu öznitelikleri oluşturulan komut özelliklerine iletir.

Örneğin, aşağıdaki gibi bir yöntemi göz önünde bulundurun:

[RelayCommand]
[property: JsonIgnore]
private void GreetUser(User user)
{
    Console.WriteLine($"Hello {user.Name}!");
}

Bu, üzerinde özniteliği olan [JsonIgnore] bir GreetUserCommand özellik oluşturur. Yöntemi hedef alan öznitelik listelerini istediğiniz kadar kullanabilirsiniz ve bunların tümü oluşturulan özelliklere iletilir.

Örnekler