WPF: После того, как я установил свойство в коде, оно навсегда игнорирует привязку XAML ... как мне это предотвратить? - PullRequest
1 голос
/ 04 апреля 2010

У меня есть кнопка с датчиком данных, который используется для отключения кнопки, если для определенного свойства не установлено значение true:

<Button Name="ExtendButton" Click="ExtendButton_Click"  Margin="0,0,0,8">
    <Button.Style>
        <Style>
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsConnected}" Value="False">
                    <Setter Property="Button.IsEnabled" Value="False" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
</Button.Style>

Это просто очень простое связывание, и оно отлично работает. Я могу установить «IsConnected» в true и false и true и false и true и false, и мне нравится видеть, как моя кнопка автоматически отключается, затем включается и т. Д. И т. Д.

Однако в моем событии Button_Click ... Я хочу:

  1. Отключить кнопку (используя ExtendButton.IsEnabled = false;)
  2. Выполнить некоторый асинхронный код (который попадает на сервер ... занимает около 1 секунды).
  3. Снова включить кнопку (используя ExtendButton.IsEnabled = true;)

Проблема в том, что в тот самый момент, когда я вручную установил для IsEnabled значение либо true, либо false ... моя привязка XAML никогда не сработает снова. Это меня очень огорчает: (

I желаю , чтобы IsEnabled был tri-state ... и что true означало true, false означало false, а null означало наследование. Но это не тот случай, так что мне делать?

Ответы [ 2 ]

2 голосов
/ 04 апреля 2010

Ответ Бенни предусматривает один подход (и отличный). Другой способ - расширить вашу модель для поддержки состояния «в асинхронной операции» и добавить еще один триггер для ответа на это:

XAML:

<Style.Triggers>
  <DataTrigger Binding="{Binding IsConnected}" Value="False">
    <Setter Property="Button.IsEnabled" Value="False" />
  </DataTrigger>
  <DataTrigger Binding="{Binding IsInAsyncOperation}" Value="True">
    <Setter Property="Button.IsEnabled" Value="False" />
  </DataTrigger>
</Style.Triggers>

Код-за:

private void ExtendButton_Click(...)
{
  IsInAsyncOperation = true;
  // begin async operation
}

private void OnAsyncOperationComplete(...)
{
  // retrieve results etc.
  IsInAsyncOperation = false;
}

Примечание. Вы можете определить свойство IsInAsyncOperation в том же классе, что и IsConnected; если это модель представления, а не класс Window, то вам необходимо соответствующим образом настроить код позади.

2 голосов
/ 04 апреля 2010

Существует намного лучший способ получить эту функциональность в WPF. Это система командования , и она потрясающая. Любая кнопка, пункт меню, горячая клавиша и т. Д. Могут быть связаны с командой single , которая автоматически обрабатывает включение / отключение (как вы хотите в своей программе). Это также чистый и многоразовый, и оооочень простой в использовании.

Например, в моем приложении у меня есть «окно диалога», которое появляется, когда пользователь нажимает клавишу F1. Я создал команду с именем AboutCommand, реализовав ICommand.

public class AboutCommand:System.Windows.Input.ICommand
{
    public bool CanExecute(object parameter)
    {
        return true; // in this case the command is never disabled
    }

    public event EventHandler CanExecuteChanged
    {
        // not needed in this case, but in commands when CanExecute actually
        // changes, this performs the "magic" of disabling/enabling your controls
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public void Execute(object parameter)
    {
        new AboutWindow().ShowDialog(); //happens when the command is executed
    }
}

Затем в xaml моего окна я добавил *:

<Window.Resources>
    <local:AboutCommand x:Key="About"/>
</Window.Resources>

<Window.InputBindings>
    <KeyBinding Command="{StaticResource About}" Gesture="F1"/>
</Window.InputBindings>

Вы можете также установить команду для кнопки следующим образом.

<Button Command="{StaticResource About}" Content="About this program"/>

Клавиша F1 и будут отключены, если AboutCommand.CanExecute() вернет false.

* (Я фактически сделал это по-другому, потому что я использую шаблон MVVM, но это работает, если вы не используете этот шаблон.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...