CanExecute ilk kez çağrıldığında WPF CommandParameter NULL olur


86

WPF ve ItemsControl'ün DataTemplate içindeki bir Düğmeye bağlı Komutlar ile ilgili bir sorunla karşılaştım. Senaryo oldukça yalındır. ItemsControl bir nesne listesine bağlıdır ve listedeki her nesneyi bir Düğmeye tıklayarak kaldırabilmek istiyorum. Düğme bir Komutu yürütür ve Komut silme işlemiyle ilgilenir. CommandParameter, silmek istediğim Nesneye bağlıdır. Bu şekilde kullanıcının neyi tıkladığını bilirim. Bir kullanıcı yalnızca "kendi" nesnelerini silebilmelidir - bu nedenle, kullanıcının doğru izinlere sahip olduğunu doğrulamak için Komutun "CanExecute" çağrısında bazı kontroller yapmam gerekiyor.

Sorun, CanExecute'a iletilen parametrenin ilk çağrıldığında NULL olmasıdır - bu nedenle komutu etkinleştirmek / devre dışı bırakmak için mantığı çalıştıramıyorum. Ancak, bunu her zaman etkinleştirirsem ve ardından komutu yürütmek için düğmeye tıklarsam, CommandParameter doğru şekilde geçirilir. Bu, CommandParameter'a karşı bağlamanın çalıştığı anlamına gelir.

ItemsControl ve DataTemplate için XAML şu şekilde görünür:

<ItemsControl 
    x:Name="commentsList"
    ItemsSource="{Binding Path=SharedDataItemPM.Comments}"
    Width="Auto" Height="Auto">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <Button                             
                    Content="Delete"
                    FontSize="10"
                    Command="{Binding Path=DataContext.DeleteCommentCommand, ElementName=commentsList}" 
                    CommandParameter="{Binding}" />
            </StackPanel>                       
         </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Gördüğünüz gibi, Yorumlar nesnelerinin bir listesine sahibim. DeleteCommentCommand öğesinin CommandParameter öğesinin Command nesnesine bağlanmasını istiyorum.

Sanırım sorum şu: bu sorunu daha önce yaşayan var mı? CanExecute, Komutumda çağrılıyor, ancak parametre her zaman ilk seferinde NULL - bu neden?

Güncelleme: Sorunu biraz azaltabildim. CommandParameter veri bağlandığında bir mesaj çıktılayabilmek için boş bir Debug ValueConverter ekledim. Sorunun, CommandParameter düğmeye bağlanmadan önce CanExecute yönteminin yürütülmesi olduğu ortaya çıktı. CommandParameter'ı Command'dan önce ayarlamayı denedim (önerildiği gibi) - ama yine de çalışmıyor. Nasıl kontrol edileceğine dair herhangi bir ipucu.

Güncelleme2: Bağlamanın ne zaman "tamamlandığını" saptamanın bir yolu var mı, böylece komutun yeniden değerlendirilmesini zorlayabilir miyim? Ayrıca bir Command nesnesinin aynı örneğine bağlanan birden çok Düğmeye (ItemsControl'deki her öğe için bir tane) sahip olmam bir sorun mu?

Güncelleme3: Hatanın bir kopyasını SkyDrive'ıma yükledim: http://cid-1a08c11c407c0d8e.skydrive.live.com/self.aspx/Code%20samples/CommandParameterBinding.zip


ListBox ile aynı problemim var.
Hadi Eskandari

Bu sorun için WPF'ye
UuDdLrLrSs

Yanıtlar:


14

Benzer bir soruna rastladım ve güvenilir TriggerConverter'ımı kullanarak çözdüm.

public class TriggerConverter : IMultiValueConverter
{
    #region IMultiValueConverter Members

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        // First value is target value.
        // All others are update triggers only.
        if (values.Length < 1) return Binding.DoNothing;
        return values[0];
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    #endregion
}

Bu değer dönüştürücü herhangi bir sayıda parametre alır ve ilkini dönüştürülen değer olarak geri gönderir. Sizin durumunuzda bir MultiBinding'de kullanıldığında aşağıdaki gibi görünür.

<ItemsControl 
    x:Name="commentsList"
    ItemsSource="{Binding Path=SharedDataItemPM.Comments}"
    Width="Auto" Height="Auto">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <Button                             
                    Content="Delete"
                    FontSize="10"
                    CommandParameter="{Binding}">
                    <Button.Command>
                        <MultiBinding Converter="{StaticResource TriggerConverter}">
                            <Binding Path="DataContext.DeleteCommentCommand"
                                     ElementName="commentsList" />
                            <Binding />
                        </MultiBinding> 
                    </Button.Command>
                </Button>
            </StackPanel>                                       
         </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Bunun çalışması için TriggerConverter'ı bir yere kaynak olarak eklemeniz gerekecek. Artık Command özelliği, CommandParameter değeri kullanılabilir hale gelmeden önce ayarlanmaz. Bunun yerine RelativeSource.Self ve CommandParameter'e bile bağlanabilirsiniz. aynı etkiyi elde etmek için.


2
Bu benim için çalıştı. Nedenini anlamadım. Biri açıklayabilir mi?
TJKjaer

Komuttan önce CommandParameter bağlanmasına neden olmuyor mu? Dönüştürücüye ihtiyacınız olacağından şüpheliyim ...
MBoros

2
Bu bir çözüm değil. Bu bir hack mi? Neler oluyor? Bu işe yaradı mı?
Ürdün

Mükemmel, benim için çalışıyor! Sihir <Binding /> satırındadır, bu da veri şablonu değiştiğinde komut bağlamanın güncellenmesine neden olur (komut parametresine bağlıdır)
Andreas Kahler

57

Görünüm modelimdeki bir komuta bağlanmaya çalışırken aynı sorunu yaşıyordum.

Öğeye adıyla atıfta bulunmak yerine göreli bir kaynak bağlama kullanmak için değiştirdim ve bu hile yaptı. Parametre bağlama değişmedi.

Eski Kod:

Command="{Binding DataContext.MyCommand, ElementName=myWindow}"

Yeni kod:

Command="{Binding DataContext.MyCommand, RelativeSource={RelativeSource AncestorType=Views:MyView}}"

Güncelleme : Bu sorunla henüz ElementName kullanmadan karşılaştım, görünüm modelimdeki bir komuta bağlanıyorum ve düğmenin veri bağlamı görünüm modelim. Bu durumda, CommandParameter özniteliğini Button bildiriminde (XAML'de) Command özniteliğinden önce taşımam gerekiyordu.

CommandParameter="{Binding Groups}"
Command="{Binding StartCommand}"

42
CommandParametresini Komutun önüne taşımak, bu konu için en iyi cevaptır.
BSick7

6
Niteliklerin sırasını değiştirmek bize yardımcı olmadı. İnfaz düzeni üzerinde bir etkisi olursa şaşırırdım.
Jack Ukleja

3
Bunun neden işe yaradığını bilmiyorum. Olmaması gerektiği gibi geliyor ama tamamen öyle.
RMK

1
Ben de aynı sorunu yaşadım - RelativeSource yardımcı olmadı, özniteliklerin sırasını değiştirdi. Güncelleme için teşekkürler!
Grant Crofton

14
XAML'i otomatik olarak güzelleştirmek için uzantıları kullanan bir kişi olarak (öznitelikleri satırlara ayırma, girintiyi düzeltme, öznitelikleri yeniden sıralama) sırasını değiştirme önerisi CommandParameterve Commandbeni korkutuyor.
Guttsy

29

Command ve CommandParameter'i ayarladığım sıranın bir fark yarattığını buldum. Command özelliğinin ayarlanması, CanExecute'un hemen çağrılmasına neden olur, bu nedenle CommandParameter'ın o noktada zaten ayarlanmasını istersiniz.

Sorununuzu çözeceğinden emin değilim, ancak XAML'deki özelliklerin sırasını değiştirmenin aslında bir etkisi olabileceğini buldum. Yine de denemeye değer.

Görünüşe göre, düğmenin hiçbir zaman etkinleştirilmemesini öneriyorsunuz, bu şaşırtıcı, çünkü CommandParameter'ın örneğinizdeki Command özelliğinden kısa bir süre sonra ayarlanmasını beklerdim. CommandManager.InvalidateRequerySuggested () öğesini çağırmak, düğmenin etkinleştirilmesine neden olur mu?


3
Komuttan önce CommandParameter'ı ayarlamayı denedim - hala CanExecute'u çalıştırıyor, ancak yine de NULL olarak geçiyor ... Bummer - ama ipucu için teşekkürler. Ayrıca, CommandManager.InvalidateRequerySuggested () 'i çağırma; herhangi bir fark yaratmaz.
Jonas Follesø

CommandManager.InvalidateRequerySuggested (), benim için benzer bir sorunu çözdü. Teşekkürler!
MJS

13

Bu sorunu çözmek için paylaşmak istediğim başka bir seçenek buldum. Komutun CanExecute yöntemi, CommandParameter özelliği ayarlanmadan önce yürütüldüğünden, bağlama değiştiğinde CanExecute yöntemini yeniden çağrılmaya zorlayan ekli bir özelliğe sahip bir yardımcı sınıf oluşturdum.

public static class ButtonHelper
{
    public static DependencyProperty CommandParameterProperty = DependencyProperty.RegisterAttached(
        "CommandParameter",
        typeof(object),
        typeof(ButtonHelper),
        new PropertyMetadata(CommandParameter_Changed));

    private static void CommandParameter_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var target = d as ButtonBase;
        if (target == null)
            return;

        target.CommandParameter = e.NewValue;
        var temp = target.Command;
        // Have to set it to null first or CanExecute won't be called.
        target.Command = null;
        target.Command = temp;
    }

    public static object GetCommandParameter(ButtonBase target)
    {
        return target.GetValue(CommandParameterProperty);
    }

    public static void SetCommandParameter(ButtonBase target, object value)
    {
        target.SetValue(CommandParameterProperty, value);
    }
}

Ve sonra bir komut parametresine bağlamak istediğiniz düğmede ...

<Button 
    Content="Press Me"
    Command="{Binding}" 
    helpers:ButtonHelper.CommandParameter="{Binding MyParameter}" />

Umarım bu, sorunla ilgili başka birine yardımcı olabilir.


Tebrikler, teşekkürler. M $ 'ın bunu 8 yıl sonra düzeltmediğine inanamıyorum. Korkunç!
McGarnagle

8

Bu eski bir iş parçacığı, ancak bu sorunu yaşadığımda Google beni buraya getirdiğinden, DataGridTemplateColumn için bir düğmeyle benim için çalışanı ekleyeceğim.

Bağlamayı şuradan değiştirin:

CommandParameter="{Binding .}"

-e

CommandParameter="{Binding DataContext, RelativeSource={RelativeSource Self}}"

Neden işe yaradığından emin değilim, ama benim için yaptı.


Yukarıdaki her iki yüksek puan cevabını da denedim, ancak bu sadece benim için çalıştı. Görünüşe göre bu, kontrolün kendi iç sorunu değil, bağlayıcı değil, ancak yine de birçok kişi onu yukarıdaki cevaplarla çalıştırdı. Teşekkürler!
Javidan

6

Son zamanlarda aynı problemle karşılaştım (benim için bir bağlam menüsündeki menü öğeleri içindi), nad her durum için uygun bir çözüm olmasa da, bunu çözmenin farklı (ve çok daha kısa!) Bir yolunu buldum sorun:

<MenuItem Header="Open file" Command="{Binding Tag.CommandOpenFile, IsAsync=True, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}" CommandParameter="{Binding Name}" />

TagBağlam menüsünün özel durumu için temelli geçici çözümü göz ardı ederek , buradaki anahtar, CommandParameterdüzenli olarak bağlamak, ancak Commandek ile bağlamaktır IsAsync=True. Bu, gerçek komutun bağlanmasını (ve dolayısıyla CanExecuteçağrılmasını) biraz geciktirecek , böylece parametre zaten mevcut olacaktır. Bu, kısa bir süre için etkin durum yanlış olabilir, ancak benim durumum için bu tamamen kabul edilebilir olduğu anlamına gelir.


5

Dün Prism forumlarındaCommandParameterBehavior yayınladığım yazımı kullanabilirsiniz . Sebepte bir değişikliğin meydana geldiği eksik davranışı ekler CommandParameter.Command yeniden sorgulanacak.

PropertyDescriptor.AddValueChangedDaha sonra aramadan ararsanız neden olan bellek sızıntısını önleme girişimlerimden kaynaklanan bazı karmaşıklıklar var.PropertyDescriptor.RemoveValueChanged . Ekement kaldırıldığında işleyicinin kaydını silerek bunu düzeltmeye çalışıyorum.

IDelegateCommandPrism kullanmıyorsanız (ve Prism kitaplığında benimle aynı değişiklikleri yapmak istemiyorsanız) muhtemelen öğeleri kaldırmanız gerekecektir . Ayrıca, RoutedCommandburada genellikle s kullanmadığımıza dikkat edin ( DelegateCommand<T>hemen hemen her şey için Prism kullanıyoruz ), bu nedenle CommandManager.InvalidateRequerySuggested, çağrım bilinen evreni veya herhangi bir şeyi yok eden bir tür kuantum dalga çöküşü çöküşü başlatırsa, lütfen beni sorumlu tutmayın .

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;

namespace Microsoft.Practices.Composite.Wpf.Commands
{
    /// <summary>
    /// This class provides an attached property that, when set to true, will cause changes to the element's CommandParameter to 
    /// trigger the CanExecute handler to be called on the Command.
    /// </summary>
    public static class CommandParameterBehavior
    {
        /// <summary>
        /// Identifies the IsCommandRequeriedOnChange attached property
        /// </summary>
        /// <remarks>
        /// When a control has the <see cref="IsCommandRequeriedOnChangeProperty" />
        /// attached property set to true, then any change to it's 
        /// <see cref="System.Windows.Controls.Primitives.ButtonBase.CommandParameter" /> property will cause the state of
        /// the command attached to it's <see cref="System.Windows.Controls.Primitives.ButtonBase.Command" /> property to 
        /// be reevaluated.
        /// </remarks>
        public static readonly DependencyProperty IsCommandRequeriedOnChangeProperty =
            DependencyProperty.RegisterAttached("IsCommandRequeriedOnChange",
                                                typeof(bool),
                                                typeof(CommandParameterBehavior),
                                                new UIPropertyMetadata(false, new PropertyChangedCallback(OnIsCommandRequeriedOnChangeChanged)));

        /// <summary>
        /// Gets the value for the <see cref="IsCommandRequeriedOnChangeProperty"/> attached property.
        /// </summary>
        /// <param name="target">The object to adapt.</param>
        /// <returns>Whether the update on change behavior is enabled.</returns>
        public static bool GetIsCommandRequeriedOnChange(DependencyObject target)
        {
            return (bool)target.GetValue(IsCommandRequeriedOnChangeProperty);
        }

        /// <summary>
        /// Sets the <see cref="IsCommandRequeriedOnChangeProperty"/> attached property.
        /// </summary>
        /// <param name="target">The object to adapt. This is typically a <see cref="System.Windows.Controls.Primitives.ButtonBase" />, 
        /// <see cref="System.Windows.Controls.MenuItem" /> or <see cref="System.Windows.Documents.Hyperlink" /></param>
        /// <param name="value">Whether the update behaviour should be enabled.</param>
        public static void SetIsCommandRequeriedOnChange(DependencyObject target, bool value)
        {
            target.SetValue(IsCommandRequeriedOnChangeProperty, value);
        }

        private static void OnIsCommandRequeriedOnChangeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (!(d is ICommandSource))
                return;

            if (!(d is FrameworkElement || d is FrameworkContentElement))
                return;

            if ((bool)e.NewValue)
            {
                HookCommandParameterChanged(d);
            }
            else
            {
                UnhookCommandParameterChanged(d);
            }

            UpdateCommandState(d);
        }

        private static PropertyDescriptor GetCommandParameterPropertyDescriptor(object source)
        {
            return TypeDescriptor.GetProperties(source.GetType())["CommandParameter"];
        }

        private static void HookCommandParameterChanged(object source)
        {
            var propertyDescriptor = GetCommandParameterPropertyDescriptor(source);
            propertyDescriptor.AddValueChanged(source, OnCommandParameterChanged);

            // N.B. Using PropertyDescriptor.AddValueChanged will cause "source" to never be garbage collected,
            // so we need to hook the Unloaded event and call RemoveValueChanged there.
            HookUnloaded(source);
        }

        private static void UnhookCommandParameterChanged(object source)
        {
            var propertyDescriptor = GetCommandParameterPropertyDescriptor(source);
            propertyDescriptor.RemoveValueChanged(source, OnCommandParameterChanged);

            UnhookUnloaded(source);
        }

        private static void HookUnloaded(object source)
        {
            var fe = source as FrameworkElement;
            if (fe != null)
            {
                fe.Unloaded += OnUnloaded;
            }

            var fce = source as FrameworkContentElement;
            if (fce != null)
            {
                fce.Unloaded += OnUnloaded;
            }
        }

        private static void UnhookUnloaded(object source)
        {
            var fe = source as FrameworkElement;
            if (fe != null)
            {
                fe.Unloaded -= OnUnloaded;
            }

            var fce = source as FrameworkContentElement;
            if (fce != null)
            {
                fce.Unloaded -= OnUnloaded;
            }
        }

        static void OnUnloaded(object sender, RoutedEventArgs e)
        {
            UnhookCommandParameterChanged(sender);
        }

        static void OnCommandParameterChanged(object sender, EventArgs ea)
        {
            UpdateCommandState(sender);
        }

        private static void UpdateCommandState(object target)
        {
            var commandSource = target as ICommandSource;

            if (commandSource == null)
                return;

            var rc = commandSource.Command as RoutedCommand;
            if (rc != null)
            {
                CommandManager.InvalidateRequerySuggested();
            }

            var dc = commandSource.Command as IDelegateCommand;
            if (dc != null)
            {
                dc.RaiseCanExecuteChanged();
            }

        }
    }
}

bağlantıda hata raporunuzla karşılaştı. Buradaki son kodunuzla gönderinizi güncelleme şansınız var mı? veya o zamandan beri daha iyi bir iş buldunuz mu?
Markus Hütter

Daha kolay bir çözüm, bir özellik tanımlayıcısı yerine bir bağlama kullanarak CommandParameter özelliğini gözlemlemek olabilir. Aksi takdirde harika bir çözüm! Bu, aslında sadece garip bir hack veya geçici çözüm sunmak yerine temeldeki sorunu çözüyor.
Sebastian Negraszus

1

DelegateCommand ile bu sorunu "düzeltmenin" nispeten basit bir yolu vardır, ancak DelegateCommand kaynağının güncellenmesini ve Microsoft.Practices.Composite.Presentation.dll dosyasının yeniden derlenmesini gerektirir.

1) Prism 1.2 kaynak kodunu indirin ve CompositeApplicationLibrary_Desktop.sln'yi açın. Burada DelegateCommand kaynağını içeren bir Composite.Presentation.Desktop projesi var.

2) Genel olay EventHandler CanExecuteChanged altında, aşağıdaki gibi değiştirin:

public event EventHandler CanExecuteChanged
{
     add
     {
          WeakEventHandlerManager.AddWeakReferenceHandler( ref _canExecuteChangedHandlers, value, 2 );
          // add this line
          CommandManager.RequerySuggested += value;
     }
     remove
     {
          WeakEventHandlerManager.RemoveWeakReferenceHandler( _canExecuteChangedHandlers, value );
          // add this line
          CommandManager.RequerySuggested -= value;
     }
}

3) Korumalı sanal boşluk altında OnCanExecuteChanged (), aşağıdaki gibi değiştirin:

protected virtual void OnCanExecuteChanged()
{
     // add this line
     CommandManager.InvalidateRequerySuggested();
     WeakEventHandlerManager.CallWeakReferenceHandlers( this, _canExecuteChangedHandlers );
}

4) Çözümü yeniden derleyin, ardından derlenen DLL'lerin yaşadığı Debug veya Release klasörüne gidin. Microsoft.Practices.Composite.Presentation.dll ve .pdb'yi (isterseniz) dış derlemelerinize başvurduğunuz yere kopyalayın ve ardından yeni sürümleri almak için uygulamanızı yeniden derleyin.

Bundan sonra, kullanıcı arabirimi söz konusu DelegateCommand'e bağlı öğeleri her oluşturduğunda CanExecute çalıştırılmalıdır.

Kendine iyi bak Joe

gmail şirketinde refereejoe


1

Benzer sorulara bazı iyi cevapları okuduktan sonra, örneğinizdeki DelegeCommand'i çalışmasını sağlamak için biraz değiştirdim. Kullanmak yerine:

public event EventHandler CanExecuteChanged;

Ben şu şekilde değiştirdim:

public event EventHandler CanExecuteChanged
{
    add { CommandManager.RequerySuggested += value; }
    remove { CommandManager.RequerySuggested -= value; }
}

Aşağıdaki iki yöntemi kaldırdım çünkü onları düzeltmek için çok tembeldim

public void RaiseCanExecuteChanged()

ve

protected virtual void OnCanExecuteChanged()

Ve hepsi bu ... bu, CanExecute'un Binding değiştiğinde ve Execute yönteminden sonra çağrılacağını garanti ediyor gibi görünüyor.

ViewModel değiştirilirse otomatik olarak tetiklenmez, ancak bu iş parçacığında belirtildiği gibi CommandManager'ı çağırarak mümkündür. GUI iş parçacığında InvalidateRequerySuggested

Application.Current?.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)CommandManager.InvalidateRequerySuggested);

Bunun DispatcherPriority.Normalgüvenilir bir şekilde (veya benim durumumda hiç) çalışamayacak kadar yüksek olduğunu buldum . Kullanımı DispatcherPriority.Loadediyi çalışır ve daha uygun görünmektedir (yani, temsilcinin görünüm modeliyle ilişkili UI öğeleri aslında yüklenene kadar çağrılmayacağını açıkça belirtir).
Peter Duniho

0

Hey Jonas, bunun bir veri şablonunda çalışıp çalışmayacağından emin değilim, ama işte bir ListView Bağlam menüsünde geçerli öğeyi bir komut parametresi olarak almak için kullandığım bağlama sözdizimi:

CommandParameter = "{Binding RelativeSource = {RelativeSource AncestorType = ContextMenu}, Path = PlacementTarget.SelectedItem, Mode = TwoWay}"


Liste görünümümde de aynı şeyi yapıyorum. Bu durumda, bu bir ItemsControl'dür, dolayısıyla (görsel ağaçta) "bağlanacak" bariz bir özellik yoktur. Sanırım bağlamanın ne zaman yapıldığını algılamanın ve CanExecute'u yeniden değerlendirmenin bir yolunu bulmalıyım (çünkü CommandParameter bağlanır, sadece geç)
Jonas Follesø


0

Bu yanıtlardan bazıları, Command'ın kendisini almak için DataContext'e bağlanmakla ilgilidir, ancak soru CommandParameter'ın olmaması gerektiği zaman boş olmasıyla ilgiliydi. Biz de bunu yaşadık. Bir önsezi üzerine, bunu ViewModel'imizde çalıştırmanın çok basit bir yolunu bulduk. Bu, özellikle müşteri tarafından bir satır kodla bildirilen CommandParameter boş sorunu içindir. Dispatcher.BeginInvoke () öğesini not edin.

public DelegateCommand<objectToBePassed> CommandShowReport
    {
        get
        {
            // create the command, or pass what is already created.
            var command = _commandShowReport ?? (_commandShowReport = new DelegateCommand<object>(OnCommandShowReport, OnCanCommandShowReport));

            // For the item template, the OnCanCommand will first pass in null. This will tell the command to re-pass the command param to validate if it can execute.
            Dispatcher.BeginInvoke((Action) delegate { command.RaiseCanExecuteChanged(); }, DispatcherPriority.DataBind);

            return command;
        }
    }

-1

Bu uzun bir atış.
bunda hata ayıklamak için şunları deneyebilirsiniz: - PreviewCanExecute olayını kontrol edin.
- içeriye göz atmak ve komut parametresinin ne olduğunu görmek için snoop / wpf köstebeği kullanın.

HTH,


Snoop'u kullanmayı denedim - ancak başlangıçta yüklendiğinde yalnızca NULL olduğu için hata ayıklamak gerçekten zor. Üzerinde Snoop'u çalıştırırsam, Command ve CommandParameter her ikisi de seth ... DataTemplate'teki Komutları kullanmakla ilgisi var.
Jonas Follesø

-1

CommandManager.InvalidateRequerySuggested benim için de çalışıyor. Aşağıdaki bağlantının benzer bir sorundan bahsettiğine inanıyorum ve M $ dev mevcut sürümdeki sınırlamayı onayladı ve commandManager.InvalidateRequerySuggested geçici çözümdür. http://social.expression.microsoft.com/Forums/en-US/wpf/thread/c45d2272-e8ba-4219-bb41-1e5eaed08a1f/

Önemli olan, commandManager.InvalidateRequerySuggested'i çağırmanın zamanlamasıdır. Bu, ilgili değer değişikliği bildirildikten sonra çağrılmalıdır.


bu bağlantı artık geçerli değil
Peter Duniho

-2

Ed Ball'un CommandParameter'i Command'dan önce ayarlama önerisinin yanında , CanExecute yönteminizin bir nesne türü parametresine sahip olduğundan emin olun .

private bool OnDeleteSelectedItemsCanExecute(object SelectedItems)  
{
    // Your goes heres
}

Umarım, CanExecute parametresi olarak SelectedItems'i nasıl alacağımı anlamak için yaptığım çok fazla zamanın birisinin harcamasını engeller

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.