【问题标题】:Change ToggleButton/RadioButton state only on external event仅在外部事件上更改 ToggleButton/RadioButton 状态
【发布时间】:2011-08-05 08:02:36
【问题描述】:

我想展示几个 ToggleButton/RadioButton 元素:

  1. 映射到枚举,这意味着 DataContext 具有“公共模式 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");
    }
}

我最初的方法是使用How to bind RadioButtons to an enum? 的解决方案,但这还不够,因为按钮状态会立即更改,即使我没有在设置器中调用 NotifyPropertyChanged。另外,我不喜欢 "GroupName" hack。

有什么想法吗?我不介意创建一个自定义按钮类,因为我需要很多这样的按钮来支持多个视图。

我正在使用 .NET 3.5 SP1 和 VS2008。

【问题讨论】:

    标签: wpf binding radio-button state togglebutton


    【解决方案1】:

    如果你想使用 RadioButtons,你只需要做一些小的调整来解决 RadioButton 的默认行为。

    您需要解决的第一个问题是 RadioButtons 基于其公共直接父容器的自动分组。由于您不喜欢“GroupName” hack,您的另一个选择是将每个 RadioButton 放入其自己的 Grid 或其他容器中。这将使每个按钮成为其自己组的成员,并强制它们根据其 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>
    

    这将我带到下一个解决方法,即确保单击的按钮在单击它后不会保持其 Checked 状态,这是触发 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));
                        });
                }
            }
        }
    

    然后在 CurrentMode 的 Setter 中调用 NotifyPropertyChanged("CurrentMode")。您可能已经需要这样的东西,因为您的 Server 的 ModeChanged 调用可能是在不是 Dispatcher 线程的线程上进入的。

    最后,如果您希望 RadioButtons 具有不同的 Checked/Unchecked 外观,您需要为它们应用样式。谷歌快速搜索 WPF RadioButton ControlTemplate 最终找到了这个站点:http://madprops.org/blog/wpf-killed-the-radiobutton-star/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多