С этим трудно справиться правильно во всех ситуациях. К сожалению, во многих популярных браузерах xhr.status
является тем же (0
), если вызов AJAX отменен навигацией или сервером, который не работает / не отвечает. Так что эта техника редко работает.
Вот набор очень «практичных» хаков, которые я накопил, которые работают довольно хорошо в большинстве случаев, но все еще не пуленепробиваемы. Идея состоит в том, чтобы попытаться перехватить события навигации и установить флаг, который проверяется в обработчике ошибок AJAX. Как это:
var global_is_navigating = false;
$(window).on('beforeunload',function() {
// Note: this event doesn't fire in mobile safari
global_is_navigating = true;
});
$("a").on('click',function() {
// Giant hack that can be helpful with mobile safari
if( $(this).attr('href') ) {
global_is_navigating = true;
}
});
$(document).ajaxError(function(evt, xhr, settings) {
// default AJAX error handler for page
if( global_is_navigating ) {
// AJAX call cancelled by navigation. Not a real error
return;
}
// process actual AJAX error here.
});
Самый простой способ, который я нашел для этого, заключается в заимствовании кучи кода. Я также думаю, что вы не хотите выставлять два события для изменения состояния. Сделайте свою команду CheckedChangedCommand вместо Checked и Unchecked. Свяжите свойство зависимостей CheckBox.IsChecked со свойством в вашем ViewModelClass. Таким образом, когда ваша команда будет выполнена, вы просто проверите это значение в вашей ViewModel.
Сначала начните использовать DelegateCommand из набора инструментов WPF ViewModel . Из вашего сообщения не ясно, являетесь вы или нет.
Затем загрузите .zip-архив из вкладки «Загрузки» по этой ссылке.
В архиве есть класс под названием EventBehaviourFactory, который делает проще настроить DependencyProperty. Вернувшись на вкладку "Главная" по указанной выше ссылке, Самуэль расскажет, как подключить команду в вашем XAML к ViewModel. Вот оно:
<TextBox ff:TextBoxBehaviour.TextChangedCommand="{Binding TextChanged}"/>
Я использовал строку из трех классов (DelegateCommand, EventBehaviourFactory и TextBoxBehaviour) для строки, и событие TextChanged сработало в моем проекте примерно за пять минут.
Шаблон для распространения его на другие элементы управления, подобные вам. делать тоже легко. Мне удалось таким же образом подключить ListBox.SelectionChanged. Создайте новый класс ControlBehaviour и замените «Control» на «TextBox» во всех экземплярах и присоедините DependencyProperty к новому событию.
Это прекрасно, когда ваш код позади пуст!
EventBehaviourFactory и TextBoxBehaviour) для строки, и событие TextChanged сработало в моем проекте примерно через пять минут.Шаблон для его распространения на другие элементы управления, как и вам, тоже прост. Мне удалось таким же образом подключить ListBox.SelectionChanged. Создайте новый класс ControlBehaviour и замените «Control» на «TextBox» во всех экземплярах и присоедините DependencyProperty к новому событию.
Это прекрасно, когда ваш код позади пуст!
EventBehaviourFactory и TextBoxBehaviour) для строки, и событие TextChanged сработало в моем проекте примерно через пять минут.Шаблон для его распространения на другие элементы управления, как и вам, тоже прост. Мне удалось таким же образом подключить ListBox.SelectionChanged. Создайте новый класс ControlBehaviour и замените «Control» на «TextBox» во всех экземплярах и присоедините DependencyProperty к новому событию.
Это прекрасно, когда ваш код позади пуст!
Другое решение, похожее на решение Эдди: Attached Command Behaviors by Marlon Grech
Вы также можете использовать свойство Command CheckBox, чтобы присоединить только одну команду, в которой вы проверьте, установлен ли флажок ...
Или вы можете привязать свойство IsChecked к свойству вашей ViewModel и реагировать на изменение в установщике этого свойства.
ну, вы можете унаследовать от элемента управления checkBox, добавить две команды в качестве свойств (Dependency Propertiess), а затем переопределить методы OnChecked и OnUnchecked и запустить каждую команду в соответствующем месте
This relates to Eddie's answer.
I played around with it a bit and it is great I also created a little template for creating new commands. I'm using it with Sharpdevelop as a code snippet. Just paste the following into your code (e.g.via a snippet):
#region $nameCommand
public static readonly DependencyProperty $nameCommand =
EventBehaviourFactory.CreateCommandExecutionEventBehaviour(
Control.$nameEvent, "$nameCommand", typeof (ControlBehavior));
public static void Set$nameCommand(DependencyObject o, ICommand value)
{
o.SetValue($nameCommand, value);
}
public static ICommand Get$nameCommand(DependencyObject o)
{
return o.GetValue($nameCommand) as ICommand;
}
#endregion
Then do a search replace for "$name" with the name of the Event/Command e.g. MouseEnter
ote, it is importand, that you make sure you pick the right classname for the owner (in my case ControlBehavior.
I am attaching a class I created for common Mouse commands in the hopes that other people share as well and we don't just implement the same thing over and over, where we could have saved a lot of time by sharing. Here my complete ControlBehavior class (I did only implement the events that I needed so far):
public static class ControlBehavior
{
#region MouseEnterCommand
public static readonly DependencyProperty MouseEnterCommand =
EventBehaviourFactory.CreateCommandExecutionEventBehaviour(
Control.MouseEnterEvent, "MouseEnterCommand", typeof (ControlBehavior));
public static void SetMouseEnterCommand(DependencyObject o, ICommand value)
{
o.SetValue(MouseEnterCommand, value);
}
public static ICommand GetMouseEnterCommand(DependencyObject o)
{
return o.GetValue(MouseEnterCommand) as ICommand;
}
#endregion
#region MouseLeaveCommand
public static readonly DependencyProperty MouseLeaveCommand =
EventBehaviourFactory.CreateCommandExecutionEventBehaviour(
Control.MouseLeaveEvent, "MouseLeaveCommand", typeof (ControlBehavior));
public static void SetMouseLeaveCommand(DependencyObject o, ICommand value)
{
o.SetValue(MouseLeaveCommand, value);
}
public static ICommand GetMouseLeaveCommand(DependencyObject o)
{
return o.GetValue(MouseLeaveCommand) as ICommand;
}
#endregion
#region MouseDoubleClickCommand
public static readonly DependencyProperty MouseDoubleClickCommand =
EventBehaviourFactory.CreateCommandExecutionEventBehaviour(
Control.MouseDoubleClickEvent, "MouseDoubleClickCommand", typeof (ControlBehavior));
public static void SetMouseDoubleClickCommand(Control o, ICommand command)
{
o.SetValue(MouseDoubleClickCommand, command);
}
public static void GetMouseDoubleClickCommand(Control o)
{
o.GetValue(MouseDoubleClickCommand);
}
#endregion
#region MouseLeftButtonDownCommand
public static readonly DependencyProperty MouseLeftButtonDownCommand =
EventBehaviourFactory.CreateCommandExecutionEventBehaviour(
Control.MouseLeftButtonDownEvent, "MouseLeftButtonDownCommand", typeof (ControlBehavior));
public static void SetMouseLeftButtonDownCommand(DependencyObject o, ICommand value)
{
o.SetValue(MouseLeftButtonDownCommand, value);
}
public static ICommand GetMouseLeftButtonDownCommand(DependencyObject o)
{
return o.GetValue(MouseLeftButtonDownCommand) as ICommand;
}
#endregion
}
By using above template it took me only a few seconds for each command.
Я сделал это с помощью триггера IsChecked, который устанавливает команду.
например.
<Style x:Key="checkBoxStyle" TargetType="{x:Type CheckBox}">
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Command"
Value="{Binding AddThingCommand}" />
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Command"
Value="{Binding RemoveThingCommand}" />
</Trigger>
</Style.Triggers>
</Style>