Próbuję zrozumieć, dlaczego CanExecute jest wywoływana ze źródła polecenia, które zostało usunięte z interfejsu użytkownika. Tutaj jest uproszczony program wykazać:Dlaczego program CanExecute jest wywoływany po usunięciu źródła poleceń z interfejsu użytkownika?
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="350" Width="525">
<StackPanel>
<ListBox ItemsSource="{Binding Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<Button Content="{Binding Txt}"
Command="{Binding Act}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Content="Remove first item" Click="Button_Click" />
</StackPanel>
</Window>
Code-tył:
public partial class MainWindow : Window
{
public class Foo
{
static int _seq = 0;
int _txt = _seq++;
RelayCommand _act;
public bool Removed = false;
public string Txt { get { return _txt.ToString(); } }
public ICommand Act
{
get
{
if (_act == null) {
_act = new RelayCommand(
param => { },
param => {
if (Removed)
Console.WriteLine("Why is this happening?");
return true;
});
}
return _act;
}
}
}
public ObservableCollection<Foo> Items { get; set; }
public MainWindow()
{
Items = new ObservableCollection<Foo>();
Items.Add(new Foo());
Items.Add(new Foo());
Items.CollectionChanged +=
new NotifyCollectionChangedEventHandler(Items_CollectionChanged);
DataContext = this;
InitializeComponent();
}
void Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Remove)
foreach (Foo foo in e.OldItems) {
foo.Removed = true;
Console.WriteLine("Removed item marked 'Removed'");
}
}
void Button_Click(object sender, RoutedEventArgs e)
{
Items.RemoveAt(0);
Console.WriteLine("Item removed");
}
}
Po kliknięciu "Usuń pierwsza pozycja" przycisk jeden raz, otrzymuję ten wynik:
Removed item marked 'Removed'
Item removed
Why is this happening?
Why is this happening?
"Dlaczego tak się dzieje?" będzie drukowany za każdym razem, gdy kliknę na pustą część okna.
Dlaczego tak się dzieje? I co mogę lub powinienem zrobić, aby zapobiec wywoływaniu CanExecute na usuniętych źródłach poleceń?
Uwaga: RelayCommand można znaleźć here.
Odpowiedzi na pytania Michael Edenfield:
Q1: callstack kiedy CanExecute jest wywoływany na usuniętym przyciskiem:
WpfApplication1.exe WpfApplication1.MainWindow.Foo.get_Act.AnonymousMethod__1 (object param) Linia 30 WpfApplication1.exe! WpfApplication1.RelayCommand.CanExecute (parametr obiektu) Linia 41 + 0x1a bajtów PresentationFramework.dll! MS.Internal.Commands.CommandHelpers.CanExecuteCommandSource (Syste m.Windows.Input.ICommandSource commandSource) + 0x8a bajtów PresentationFramework.dll! System.Windows.Controls.Primitives.ButtonBase.UpdateCanExecute() + 0x18 bajtów PresentationFramework.dll! System.Windows.Controls.Primitives.ButtonBase.OnCanExecuteChanged (obiekt sender, System.EventArgs e) + 0x5 bajtów PresentationCore.dll! System.Windows.Input.CommandManager.CallWeakReferenceHandlers (System.Collections.Generic.List)) + 0xac bajtów PresentationCore.dll! System.Windows.Input.CommandManager. RaiseRequerySuggested (object obj) + 0xf bajtów
Q2: (? nie tylko pierwszy) także, czy to dzieje się zachować, jeśli usunąć wszystkie przyciski z listy
Tak.
Tęsknię za RelayCommand. Co to jest? – Gqqnbig
Dodałem link do implementacji RelayCommand. –
Czy próbowałeś sprawdzić dzwonek podczas wydarzenia i zobaczyć, co go spowodowało? Czy to też się dzieje, jeśli usuniesz * wszystkie * przycisków z listy (nie tylko pierwszego?) –