Mvvm 集合中项目之间的互斥属性

Mvvm 集合中项目之间的互斥属性,mvvm,caliburn.micro,Mvvm,Caliburn.micro,我已经大大简化了这一点,但是我有一个问题,那就是如何最好地解决这个问题 在附带的屏幕截图中,我要求只能有一个主要联系人。用户应该能够从列表视图(屏幕快照的左侧)或详细视图(屏幕快照的右侧)更改主要联系人 换句话说,如果用户要在列表视图中选中Jane Doe,则会取消选中John Smith旁边的复选框。在细节视图中也会出现同样的情况,如果选中Jane Doe的复选框,则取消选中John Smith 我正在使用Caliburn.Micro作为我的MVVM框架,并附上了示例项目 我试图使项目变得非常

我已经大大简化了这一点,但是我有一个问题,那就是如何最好地解决这个问题

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

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

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

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


谢谢

在我看来,这里有几个基本选项。我的方向是创建一个名为Person的模型对象,并具有一个名为IsPrimary的布尔属性。我会让这个模型对象实现INotifyPropertyChanged。在我的ViewModel对象中,我将有一个Person对象的BindingList集合对象。然后为复选框连接一些命令以触发Person对象中的更改,这应该可以做到。

业务对象负责确定如果一个项成为主项,其他项会发生什么情况,因此您需要某种类型的对象来管理
IsPrimary
标志

无论您如何操作(自定义容器类型、中介器等),您都需要一些东西来协调更改

e、 g

公共类中介程序
{
IList_contacts=null;
公共调解员(IList联系人)
{
_触点=触点;
foreach(触点中的var c)
{
c、 PropertyChanged+=ContactPropertyChanged;
}
}
private bool_ischange=false;
private void ContactPropertyChanged(对象发送方,PropertyChangedEventArgs e)
{
var电流=发送器作为触点;
if(e.PropertyName==“IsPrimary”&&!\u isChanging&¤t.IsPrimary)
{
_IsChange=真;
foreach(变量c在_触点中,其中(x=>x!=当前)
{
c、 IsPrimary=false;
}
_IsChange=假;
}
}
}
可能有更好的方法,比如拥有一个容器集合(它自己钩住propertychanged等…还要注意事件处理程序!)

您可以编写一个更通用的模板版本来触发重载(因此您可以轻松地创建子类来创建不同的中介体等)

公共类中介程序
{
IList_items=null;
公共中介(IList项、参数字符串[]watchedProperties){…等
受保护的虚拟OnWatchedPropertyChanged(T发送方,字符串PropertyName)
{
}
}
公众联络调解员:调解员
{
公共ContactMediator(IList联系人,参数字符串[]watchedProperties){。。。
重写OnWatchedPropertyChanged(联系人对象、字符串propertyName){…等
}

当然,我在原始问题的解决方案中已经有了这一点。复杂的是确保只有一个主要联系人。在我的实际应用程序中,我已经有一个收集类(即ContractCollection)来管理此需求。但是我选择了一个非常复杂的方法:).我更喜欢这种方法.谢谢你的帮助!
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
}