【问题标题】:How to convert bitmasked values to an options object?如何将位掩码值转换为选项对象?
【发布时间】:2012-04-17 06:12:00
【问题描述】:

我必须读/写一个将其数据存储为位掩码值的 XML 文件。

例如

<panel>
    <options arming="21" opt_b="51" opt_c="6" />
</panel>

在这种情况下,arming 的值为 21,但这对应于以下字节字符串:

10101

这些字节对应于以下列表中的选项 0、2、4:

  • 位 0:强制启动
  • 位 1:最后一扇门
  • 位 2:退出故障
  • 位 3:禁止篡改
  • 位 4:显示
  • 位 8:重新武装
  • 位 9:行
  • 位 10:扩展块

对我来说最好的方法是什么

  • 将其从21 的十进制值转换为代表选项的对象模型?
  • 使用该对象将这些显示为供用户选择和取消选择的选项?

【问题讨论】:

    标签: c# wpf xml bitmask


    【解决方案1】:

    这样声明一个枚举:

    [Flags]
    public enum ArmingFlags {
       None=0
       Forced_arm = 1
       Final_door = 2
       Exit_fault = 4
       Inhibit_tamper = 8
       Display = 16
       Rearm = 32
       Line = 64
       Extend_block = 128
    }
    

    注意我在枚举中使用了 2 的幂。这些允许枚举使用二进制位位置来表示离散值(请参阅Why do enum permissions often have 0, 1, 2, 4 values?

    然后将您的值解析为整数并将其转换为 ArmingFlags 类型(注意,前面的未经测试的代码,但应该可以工作):

    ArmingFlags flagsVal = ArmingFlags.None;
    Int32 val;
    if (Int32.TryParse(armingString, out val)) {
        flagsVal = (ArmingFlags)val;
    }
    
    // Then you can test it for expected values:
    if ((flagsVal & ArmingFlags.Rearm) == ArmingFlags.Rearm) {
        //The Rearm bit was set...
    }
    

    有很多关于如何在 WPF 组合框或单选按钮中使用枚举的帖子,例如:

    Databinding an enum property to a ComboBox in WPF

    【讨论】:

    • 谢谢,这行得通。注意 - 我已经编辑了答案以添加一些括号。只是想知道,为什么要写((flagsVal &amp; ArmingFlags.Rearm) == ArmingFlags.Rearm)(flagsVal == ArmingFlags.Rearm) 不会同样工作吗?这似乎是多余的,但我已经看到了其他几个类似的例子。不过,当我使用这两个示例对其进行测试时,它仍然有效。
    • 您想在(可能)多个标志中测试单个标志。例如,您在 OP (10101) 中显示的值不等于 ArmingFlags.Forced_arm (它是ArmingFlags.Forced_arm &amp; ArmingFlags.Exit_fault &amp; ArmingFlags.Display)。要测试特定标志位,您需要过滤掉值中的所有其他 1,然后执行相等测试。
    • 真的最好在我上面链接的帖子中解释:stackoverflow.com/questions/9811114/…
    【解决方案2】:

    如何利用枚举的力量来帮助你:

    [Flags]
    public enum AlarmData
    {
        ForcedArm = 1,
        FinalDoor = 2,
        ExitFault = 4,
        InhibitTamper = 8,
        Display = 16,
        Rearm = 32,
        Line = 64,
        ExtendBlock = 128
    }
    
    private static Dictionary<AlarmData, string> alarmDataLookup = new Dictionary<AlarmData, string>
    {
        { AlarmData.ForcedArm, "Forced arm" },
        { AlarmData.FinalDoor, "Final door" },
        { AlarmData.ExitFault, "Exit fault" },
        { AlarmData.InhibitTamper , "Inhibit tamper" },
        { AlarmData.Display , "Display" },
        { AlarmData.Rearm , "Rearm" },
        { AlarmData.Line , "Line" },
        { AlarmData.ExtendBlock , "Extend block" }
    };
    
    public IEnumerable<string> EnumerateValues(AlarmData data)
    {
        return from pair in alarmDataLookup 
                where data.HasFlag(pair.Key) 
                select pair.Value;
    }
    

    从 XML 中读取值后,调用 EnumerateValues 很简单,只需将整数转换为 AlarmData 枚举,例如:

    int value = GetAlarmValueFromXml();
    var bindableValues = EnumerateValues((AlarmData)value);
    

    当然,您不必从 EnumerateValues 方法返回字符串。然后,您需要做的就是将该方法的结果绑定到一个列表或其他一些元素,而 Bob 就是您的叔叔。

    【讨论】:

      猜你喜欢
      • 2019-02-25
      • 2021-07-15
      • 1970-01-01
      • 2022-10-18
      • 2014-09-16
      • 1970-01-01
      • 2020-12-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多