【问题标题】:Two properties - Second property type depends on first property两个属性 - 第二个属性类型取决于第一个属性
【发布时间】:2015-08-09 18:09:12
【问题描述】:

我创建了一个包含两个变量的类:Type & Value。如果第一个属性 (Type) 已填充,则第二个属性 (Value) 只能包含与在 Type 属性上选择的类型匹配的值。

public class Requirement
{
    public RequirementType Type { get; set; }
    public object Value { get; set; }  

    public enum RequirementType
    {
        OS, NetFramework, Connection
    }             
    public enum OSType
    {
        // Used for RequirementType.OS
        Win, Unix, MacOSX
    }
    public enum NetFrameworkType
    {
        // Used for RequirementType.NetFramework
        Two, Three, Four, FourHalf
    }
    public enum ConnectionType
    {
        // Used for RequirementType.Connection
        Internet, Connected, None
    }  
}

我在 XAML 中使用这个类:

<util:Requirement Type="OS" Value="Win" />

例如,如果选择了枚举值OS。唯一有效的值应该来自枚举OSType。我开始在 .Net 源中查看他们如何使用 System.Windows.TriggerSystem.Windows.Setter 解决这个问题,但还没有成功。这似乎与 DependsOn 属性和 XamlSetTypeConverterAttribute 有关。有人知道这个问题的解决方案吗?

【问题讨论】:

  • 为什么你需要一个单独的类呢?我有 3 个课程 OSRequirementNetFrameworkRequirementConnectionRequirement
  • 我想这样解决。但如果无法实现,我肯定会使用它作为后备。
  • 为什么是Value is object
  • 这是一个很好的问题,他们是如何实现触发器和设置器的。
  • 像@weston 一样,我建议使用不同的类(可能会或可能不会从公共基类继承)。原因很简单:在 XAML 中,属性没有顺序:用户可以在 Type 属性之前设置 Value 属性。这也意味着 XAML 解析器可以按任何顺序评估它们。

标签: c# wpf properties


【解决方案1】:

您可以使用支持字段作为值并在设置时检查每种类型。

public class Requirement
{
    public RequirementType Type { get; set; }

    private object _value;
    public object Value 
    { 
        get { return _value; }
        set
        {
            if (Type == RequirementType.OS && 
                value.GetType() == typeof(OSType))
            {
                _value = value;
            }
            else 
            {
                throw new Exception("Value type is incorrect for Type provided");
            }
        }
    }  
}

这个测试会抛出异常:

var req = new Requirement();
req.Type = RequirementType.OS;
req.Value = RequirementType.Connection;

虽然第二个测试将正确设置值:

var req = new Requirement();
req.Type = RequirementType.OS;
req.Value = OSType.Win;

【讨论】:

    【解决方案2】:

    您可以使用普通属性(输入propful并点击Tab):

    private RequirementType _type;
    public RequirementType Type
    {
        get { return _type; }
        set
        {
            _type = value;
            // do whatever logic you want here
        }
    }
    

    【讨论】: