Изменение состояния ToggleButton / RadioButton только для внешнего события - PullRequest
3 голосов
/ 14 апреля 2011

Я хочу представить несколько элементов ToggleButton / RadioButton, которые:

  1. соответствуют перечислению, что означает, что DataContext имеет свойство "Public Mode CurrentMode".
  2. являются взаимоисключающими (проверяется только одна кнопка)
  3. При нажатии кнопки состояние не изменяется немедленно.Вместо этого запрос отправляется на сервер.Состояние изменяется при получении ответа.
  4. Иметь другое изображение для отмеченного / непроверенного состояния

Например, 4 кнопки отображают следующую модель представления:

public class ViewModel
{
    public enum Mode { Idle, Active, Disabled, Running }
    Mode m_currentMode = Mode.Idle;

    public Mode CurrentMode
    {
        get { return m_currentMode; }
        set
        {
            SendRequest(value);
        }
    }

    // Called externally after SendRequest, not from UI
    public void ModeChanged(Mode mode)
    {
        m_currentMode = mode;
        NotifyPropertyChanged("CurrentMode");
    }
}

Мой первоначальный подход состоял в том, чтобы использовать решение из Как связать RadioButtons с перечислением? , но этого недостаточно, поскольку состояние кнопки изменяется немедленно, даже если я не вызываю NotifyPropertyChanged всеттер.Кроме того, мне не нравится взлом "GroupName".

Есть идеи?Я не против создать пользовательский класс кнопок, так как мне нужно много таких кнопок для нескольких представлений.

Я использую .NET 3.5 SP1 и VS2008.

1 Ответ

0 голосов
/ 16 июня 2011

Если вы хотите использовать RadioButton, вам просто нужно сделать несколько небольших настроек, чтобы обойти стандартное поведение RadioButton.

Первая проблема, которую необходимо обойти, - автоматическая группировка кнопок RadioButton на основе их общего непосредственного родительского контейнера.Поскольку вам не нравится взлом "GroupName", другой вариант - поместить каждую кнопку RadioButton в свою собственную таблицу или другой контейнер.Это сделает каждую кнопку членом ее собственной группы и заставит их вести себя в зависимости от привязки IsChecked.

    <StackPanel Orientation="Horizontal">
        <Grid>
            <RadioButton IsChecked="{Binding Path=CurrentMode, Converter={StaticResource enumBooleanConverter}, ConverterParameter=Idle}">Idle</RadioButton>
        </Grid>
        <Grid>
            <RadioButton IsChecked="{Binding Path=CurrentMode, Converter={StaticResource enumBooleanConverter}, ConverterParameter=Active}">Active</RadioButton>
        </Grid>
        <Grid>
            <RadioButton IsChecked="{Binding Path=CurrentMode, Converter={StaticResource enumBooleanConverter}, ConverterParameter=Disabled}">Disabled</RadioButton>
        </Grid>
        <Grid>
            <RadioButton IsChecked="{Binding Path=CurrentMode, Converter={StaticResource enumBooleanConverter}, ConverterParameter=Running}">Running</RadioButton>
        </Grid>
    </StackPanel>

Это подводит меня к следующему обходному пути, который гарантирует, что нажатие кнопки не останетсяв проверенном состоянии после нажатия на него, который был необходим для запуска вызова set, поскольку вы привязываете свойство IsChecked.Вам нужно будет отправить дополнительный NotifyPropertyChanged, но он должен быть помещен в очередь потока Dispatch, чтобы кнопка получила уведомление и обновила свою визуальную привязку IsChecked.Добавьте это к вашему классу ViewModel, который, вероятно, заменяет вашу существующую реализацию NotifyPropertyChanged, и я предполагаю, что ваш класс реализует INotifyPropertyChanged, которого нет в коде вопроса:

    public event PropertyChangedEventHandler PropertyChanged;
    protected void NotifyPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            Dispatcher uiDispatcher = Application.Current != null ? Application.Current.Dispatcher : null;
            if (uiDispatcher != null)
            {
                uiDispatcher.BeginInvoke(DispatcherPriority.DataBind,
                    (ThreadStart)delegate()
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                    });
            }
        }
    }

Затем в вызове Setter вашего CurrentMode вызов NotifyPropertyChanged"CurrentMode").Возможно, вам уже нужно что-то подобное, так как ваш запрос ModeChanged вашего сервера, вероятно, поступает в поток, который не является потоком Dispatcher.

Наконец, вам нужно применить стиль к вашим RadioButtons, если вы хотите, чтобы они имелидругой проверенный / непроверенный вид.Быстрый поиск Google для WPF RadioButton ControlTemplate в конечном итоге пришел к этому сайту: http://madprops.org/blog/wpf-killed-the-radiobutton-star/.

...