【问题标题】:Know which collection contains me!知道哪个收藏包含我!
【发布时间】:2011-05-12 10:10:52
【问题描述】:

在我的 Silverlight 4 项目中,我有一个实现接口的简单类,例如:

public interface IMyClass
{
  string Name { get; set; }
  anyotherclass Value { get; set; }
}

父类包含一组 IMyClass 元素,例如:

public class ParentClass
{
  ObservableCollection<IMyClass> Children { get; }
}

现在我想确保 IMyClass.Name 在 Children 集合中是唯一的。用户可以更改 IMyClass.Name - 所以我需要验证名称是否已经在集合中。我想使用 Silverlight 异常和验证机制,我的 XAML 文本框看起来像:

<TextBox Text="{Binding 
                ValidatesOnExceptions=true,
                NotifyOnValidationError=true,
                Mode=TwoWay,
                Path=Name}"/>

所以我需要检查 Name 属性的设置器,例如:

public string Name
{
    get { return _name; }
    set 
    {
        if (value == _name)
            return;

        if (CollectionAlreadyContainsName(this, value))
            throw new ArgumentException("The name already exists");
        else
            _name = value;

        OnPropertyChanged("Name");
    }
}

问题来了:CollectionAlreadyContainsName 需要知道集合,但在 IMyClass 对象中我不知道我在哪个集合中。我需要保留对父级的引用,例如

public interface IMyClass
{
  string Name { get; set; }
  anyotherclass Value { get; set; }
  ParentClass Parent { get; }
}

由于交叉引用以及需要确保始终正确设置父级,这对我来说很糟糕。所以我寻找另一种方法来做到这一点。一个想法是让 ParentClass 监听 IMyClass 的 NameChanged 事件,并在必要时恢复名称更改。但这不适用于上述 Silverlight 异常和验证机制。

任何想法如何解决这个问题?

提前致谢,
弗兰克

【问题讨论】:

    标签: c# silverlight validation binding


    【解决方案1】:

    您赋予 IMyClass 错误的责任。它不知道集合,也不应该知道。

    集合类的职责是只添加名称不同的对象。

    因此覆盖/创建一个添加方法来执行此操作,并将名称设为只读或订阅集合中名称的更改并在那里引发错误。

    编辑

    不要还原属性。这不是收藏的责任。

    【讨论】:

    • 使用 Silverlight 验证和异常机制,我需要(据我所知)验证 setter 中的条目并引发异常,如果出现问题 - 就像已经有另一个对象包含列表中的给定名称。我想保持通知用户输入错误的机制,因为它已经内置并且易于实现(它只是在设置器中的抛出和用户控件中的两个属性:))
    • 我理解但不同意。该类应该知道该集合。您可以向集合添加验证。 SL 中的验证以这种方式工作的事实并不是搞砸责任的好借口。这当然取决于你。只是我的 2c。
    • 我完全同意你的看法。数据绑定应该以某种方式与集合的验证机制一起使用,例如:用户输入 -> 集合验证 -> 将用户输入传播到对象或引发异常。不幸的是,这种行为并没有内置在 SL 中(据我所知),手动实现会导致大量开销,我试图避免这种情况。
    【解决方案2】:

    这里的问题是它不是那么简单;一个对象可以被零个、一个或许多、许多个集合引用。假设孩子有充分的 OO 理由了解父母(这实际上很少见),您需要决定您需要支持哪个。我不会在这里使用事件,因为事件也是多播,可能会造成混淆。

    如果它是一个强大的父/子关系,那么无论如何添加一个父属性,但你应该强制它 - 即你不能意外添加一个已经是子属性的对象另一个集合,添加它应该设置父集合。

    您还应该确保只有一个 Add api - 即您是否在对象上调用方法?或收藏?两种方法都可以,但是使用一种方法可以避免混乱。您几乎肯定需要一个自定义集合来执行此操作,以避免默认的 Add 实现。

    【讨论】:

    • 我已经害怕了,这不是那么简单的g。想要在名称设置器中检查完整性的主要原因是使用 Silverlight 验证和异常机制,它提供了一种简单而好的方法来检查条目并将反馈返回给用户。另一个问题是,用户可以在之后更改名称,因此仅仅“控制”添加方法是不够的。除了制作好的 OO 之外,我尽量不要过度设计并尽可能多地使用(良好工作的)标准方法/类。
    【解决方案3】:

    接口中不需要Parent 属性,只需要实现类中的数据成员。将父级传递给构造函数。

    【讨论】:

    • 这是可能的,但我忘了告诉你关于 XML 序列化的信息,它需要一个无参数的构造函数和用于反序列化的公共 setter 属性。 (它仍然是一种交叉引用)
    猜你喜欢
    • 1970-01-01
    • 2018-10-03
    • 2016-11-12
    • 1970-01-01
    • 2011-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-08
    相关资源
    最近更新 更多