#c# #wpf #data-binding
#c# #wpf #привязка к данным
Вопрос:
У меня есть кнопка, IsEnabled
свойство которой привязано в моей модели представления к значению, указывающему, были ли изменены данные в текущем представлении. До сих пор эта привязка работала нормально, пока я не попытался добавить функциональность перетаскивания в ItemsControl в представлении.
Функция перетаскивания работает нормально и делает все, что должна. Когда он завершает любые необходимые манипуляции с данными, он устанавливает свойство модели представления IsModified
true
равным . Я проверил, что значение действительно установлено true
равным .
Проблема, с которой я сталкиваюсь, заключается в том, что при изменении IsModified
свойства из моего Drop
метода свойство кнопки IsEnabled
не обновляется; когда IsModified
установлено значение true
во время операции перетаскивания, кнопка остается отключенной. Если я нажимаю на кнопку, она внезапно обновляется и становится включенной, требуя, чтобы я нажал кнопку второй раз, чтобы действительно сделать то, что задумано.
Drop
Метод вызывается при Drop
событии элемента ItemsControl. Вызывается ли это из другого потока или что-то, что не информирует пользовательский интерфейс об изменении свойства? Я пытался найти вспомогательные документы, но у меня возникли небольшие проблемы.
Еще раз, установка IsModified
свойства продолжает работать при любых других обстоятельствах и правильно обновляет пользовательский интерфейс.
Рассматриваемый код довольно прост.
XAML:
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<EventSetter Event="DragEnter" Handler="IcFields_DragEnter"/>
<EventSetter Event="Drop" Handler="IcFields_Drop"/>
</Style>
</ItemsControl.ItemContainerStyle>
...
...
...
<Button Margin="5" Padding="10,0,10,0" IsEnabled="{Binding IsModified}"
Command="{Binding SaveChangesCommand}">Save Changes</Button>
где IcFields_Drop
обработчик разрешает вносить изменения в модель и, в конце концов, устанавливает IsModified
значение true
.
Редактировать:
Вот сокращенный пример реализации. Используйте приведенный выше XAML в качестве XAML для этого примера.
C # — Code-Behind
private void IcFields_Drop(object sender, DragEventArgs e)
{
ViewModel.Drop();
}
C # — Модель представления
private bool isModified;
public bool IsModified
{
get { return isModified; }
set { SetProperty(ref isModified, value); }
}
public void Drop()
{
//PSEUDO: Do some drag/drop logic for the items attached to the ItemsControl.
...
...
IsModified = true;
}
Комментарии:
1. Попробуйте это
IsEnabled="{Binding IsModified, UpdateSourceTrigger=PropertyChanged}"
2. К сожалению, @ikerbera не справился с задачей.
3.
IsEnabled="{Binding IsModified, UpdateSourceTrigger=PropertyChanged}, Mode=OneWay"
. Я обычно используюMode=TwoWay
, но в данном случае это кажется немного излишним. Взгляните на это4. @ikerbera
Mode=TwoWay
— это бессмыслица, поскольку элемент управления никогда активно не обновляет свое свойство IsEnabled, следовательно, нет направления привязки от цели к источнику.UpdateSourceTrigger=PropertyChanged
также бессмысленно, потому что это влияет только на привязки TwoWay или OneWayToSource.5. Реализует ли ваша модель представления (поскольку код не показан) inotifypropertychanged ?
Ответ №1:
Вместо того, чтобы привязывать IsEnabled
свойство, вы должны вернуть a bool
из CanExecute
метода вашей команды, чтобы указать Button
, должно ли оно быть включено. Затем вы должны вызвать метод, который вызывает CanExecuteChanged
событие команды в вашем Drop()
методе.
Большинство ICommand
реализаций включают RaiseCanExecuteChanged()
метод или аналогичный, который вы можете вызвать, чтобы обновить статус команды:
public void Drop()
{
...
SaveChangesCommand.RaiseCanExecuteChanged();
}
Комментарии:
1. Это отличный момент. Я
IsEnabled
привязал, когда мне это действительно не нужно, так что я могу, по крайней мере, отказаться от этого. В настоящееRaiseCanExecuteChanged()
время в моей реализации нет метода, поэтому я подумаю о его добавлении. На данный момент, однако, похоже, что что-то происходит в конце моего перетаскивания; он не обновляется до тех пор, пока не будет нажата в любом месте экрана.IsEnabled
Изучаю это.2. @pseudorian: вы могли бы взглянуть на то, как это реализовано, например, в MVVMLight .
3. Это действительно сработало для меня, спасибо! Я все еще не уверен, почему только
Drop
событие вызывает эту проблему, поэтому я собираюсь продолжить ее изучение, но, по крайней мере, это работает, и у меня есть немного лучшаяICommand
реализация для работы.