3

我想展示几个 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");
    }
}

我最初的方法是使用如何将 RadioButtons 绑定到枚举中的解决方案?,但这还不够,因为按钮状态会立即更改,即使我没有在 setter 中调用 NotifyPropertyChanged。此外,我不喜欢“GroupName”黑客。

有任何想法吗?我不介意创建一个自定义按钮类,因为我需要许多这样的按钮来实现多个视图。

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

4

1 回答 1

0

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

您需要解决的第一个问题是 RadioButtons 基于其公共直接父容器的自动分组。由于您不喜欢“GroupName”破解,您的另一个选择是将每个 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。谷歌快速搜索 WPF RadioButton ControlTemplate 最终找到了这个网站: http: //madprops.org/blog/wpf-killed-the-radiobutton-star/

于 2011-06-16T14:47:47.483 回答