Tôi thực sự gãi đầu với cái này. Tôi có một cửa sổ chính mở ra một hộp thoại. Sau khi hộp thoại đóng, phương thức CanExecute trên các lệnh bị ràng buộc trong hộp thoại vẫn đang thực hiện. Điều này đang gây ra một số vấn đề nghiêm trọng trong đơn đăng ký của tôi.Khi nào ui tách khỏi lệnh?
Ví dụ:
MainWindow có nút có trình xử lý nhấp chuột. Đây là xử lý sự kiện click:
private void Button_Click(object sender, RoutedEventArgs e)
{
DialogWindow window = new DialogWindow();
window.ShowDialog();
}
Trong hộp thoại tôi ràng buộc một mục kiểm soát tới một tài nguyên tĩnh trong cửa sổ hộp thoại, và mỗi mục trong danh sách có một lệnh:
<Window.Resources>
<Collections:ArrayList x:Key="itemsSource">
<local:ItemViewModel Description="A"></local:ItemViewModel>
<local:ItemViewModel Description="B"></local:ItemViewModel>
<local:ItemViewModel Description="C"></local:ItemViewModel>
</Collections:ArrayList>
<DataTemplate DataType="{x:Type local:ItemViewModel}">
<Button Grid.Column="1" Command="{Binding Path=CommandClickMe}" Content="{Binding Path=Description}" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}">
</Button>
</DataTemplate>
</Window.Resources>
<Grid>
<ToolBar ItemsSource="{StaticResource itemsSource}"></ToolBar>
</Grid>
Đây là viewmodel:
public class ItemViewModel
{
private RelayWpfCommand<object> _commandClickMe;
public RelayWpfCommand<object> CommandClickMe
{
get
{
if (_commandClickMe == null)
_commandClickMe = new RelayWpfCommand<object>(obj => System.Console.Out.WriteLine("Hei mom"), obj => CanClickMe());
return _commandClickMe;
}
}
private bool CanClickMe()
{
return true;
}
public string Description { get; set; }
Và đây là việc thực hiện DelegateCommand:
public class RelayWpfCommand<T> : ICommand
{
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
private readonly Predicate<T> _canExecute;
private readonly Action<T> _execute;
public RelayWpfCommand(Action<T> execute, Predicate<T> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
/// <summary>
/// Forces a notification that the CanExecute state has changed
/// </summary>
public void RaiseCanExecuteChanged()
{
CommandManager.InvalidateRequerySuggested();
}
public bool CanExecute(T parameter)
{
return _canExecute(parameter);
}
public void Execute(T parameter)
{
_execute(parameter);
}
bool ICommand.CanExecute(object parameter)
{
if (!IsParameterValidType(parameter))
return false;
return CanExecute((T)parameter);
}
void ICommand.Execute(object parameter)
{
if (!IsParameterValidType(parameter))
throw new ArgumentException(string.Format("Parameter must be of type {0}", typeof(T)));
Execute((T)parameter);
}
private static bool IsParameterValidType(object parameter)
{
if (parameter != null && !typeof(T).IsAssignableFrom(parameter.GetType()))
return false;
return true;
}
}
Bây giờ, nếu tôi đóng cửa sổ hộp thoại và đặt điểm ngắt trong phương thức CanExecute (Tôi đang sử dụng Prism DelegateCommand với đăng ký sự kiện yếu) trên viewmodel, tôi nhận thấy rằng nó kích hoạt mặc dù hộp thoại đã bị đóng. Tại sao trên trái đất là sự ràng buộc giữa các nút trong hộp thoại và lệnh trên ViewModel vẫn còn sống?
Và tôi đang kiểm tra xem nó đang được thực hiện bằng cách đóng cửa sổ và sau đó thiết lập một điểm ngắt trong phương thức "CanClickMe" trong chế độ xem. Nó sẽ được thực hiện trong một thời gian, sau đó đột nhiên dừng lại (có thể do GC). Hành vi không xác định này đang gây ra vấn đề bởi vì trong ứng dụng thực tế, viewmodel có thể đã được xử lý.
Tại thời điểm nào bạn thấy điều này? Ví dụ cửa sổ sẽ vẫn nằm trong phạm vi sau khi nó đóng, cho đến khi bạn rời khỏi sự kiện Click. Điều này cho phép người gọi truy cập các thuộc tính trong cửa sổ (ví dụ, trong cửa sổ Tùy chọn). Ngoài ra, những gì trong CanExecute đang gây ra một vấn đề? Có thể vấn đề thực sự là bạn đang tạo ra các hiệu ứng phụ trong CanExecute? –
Xem nhận xét của tôi – Marius