集合中项目的互斥属性

时间:2013-01-06 19:51:22

标签: mvvm caliburn.micro

Screenshot

我已大大简化了这一点,但我对这个解决这个问题的最佳方法有疑问。

在附带的屏幕截图中,我要求只能有一个主要联系人。用户应该能够从列表视图(屏幕截图的左侧)或详细视图(屏幕截图的右侧)更改主要联系人。

换句话说,如果用户要在列表视图中检查Jane Doe,则会取消选中John Smith旁边的复选框。在详细信息视图中也会出现相同的情况,如果选中Jane Doe的复选框,则会取消选择John Smith。

我正在使用Caliburn.Micro作为我的MVVM框架,并附加了示例项目。

我试图让项目变得非常简单。我没有解决附加项目中的问题,我希望对如何解决它有不同的想法。

WpfApplication1.zip

由于

2 个答案:

答案 0 :(得分:1)

业务对象有责任确定如果其他项成为主要项目会发生什么,因此您需要某种管理IsPrimary标志的对象。

但是你这样做(自定义容器类型,中介等)你需要一些东西来调解变化

e.g。

public class Mediator
{
    IList<Contact> _contacts = null;

    public Mediator(IList<Contact> contacts) 
    {
        _contacts = contacts;

        foreach(var c in contacts) 
        {
            c.PropertyChanged += ContactPropertyChanged;
        }
    }

    private bool _isChanging = false;

    private void ContactPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        var current = sender as Contact;

        if(e.PropertyName == "IsPrimary" && !_isChanging && current.IsPrimary)
        {
            _isChanging = true;

            foreach(var c in _contacts.Where(x => x != current) 
            {
                c.IsPrimary = false;
            }

            _isChanging = false;
        }
    }
}

可能有更好的方法,例如拥有一个容器集合(它可以自己挂起属性等等......还要注意事件处理程序!)

您可以编写一个更通用的模板化版本来激发重载(因此您可以轻松地创建不同的调解器等子类)

public class Mediator<T>
{
    IList<T> _items = null;

    public Mediator(IList<T> items, params string[] watchedProperties) { ... etc

    protected virtual OnWatchedPropertyChanged(T sender, string PropertyName) 
    {
    }
}

public ContactMediator : Mediator<Contact>
{
     public ContactMediator(IList<Contact> contacts, params string[] watchedProperties) { ...

     override OnWatchedPropertyChanged(Contact object, string propertyName) { ... etc
}

答案 1 :(得分:0)

正如我所看到的,有几个基本选项。我要去的方向是创建一个名为Person的Model对象,并有一个名为IsPrimary的布尔属性。我希望这个模型对象实现INotifyPropertyChanged。在我的ViewModel对象中,我将拥有Person对象的BindingList集合对象。然后为复选框连接一些命令以触发Person对象中的更改,并且应该这样做。