Tim Schumacher
Tim Schumacher

Reputation: 153

How to implement chained/proxied databindings

I have this problem in my mvvm wpf application where I want to create proxied/chained databindings.

My ModelViewController looks like this:

public class ListViewModel
{
    public ObservableCollection<Contact> GridData { get; private set; }
    public ObservableCollection<Contact> SelectedEntities { get; private set; }
    public bool IsSingeselect { get { return SelectedEntities.Count == 1; } }
    public bool IsMultiSelect { get { return SelectedEntities.Count > 0; } }
    public ObservableCollection<MenuComandModel> ContextMenuItems { get; private set; }
}

GridData and SelectedEntities is bound to a datagrid and works like a charm. I'm using the ContextMenuItems collection to create BarButtonItems for the datagrids contextmenu, this works very good. The MenuComandModel class has a Enabled attribute and I want to bind this on the IsSingeselect or IsMultiSelect attribute to the BarButtonItems member IsEnabled . How would I archive this?

Upvotes: 0

Views: 62

Answers (1)

DmitryG
DmitryG

Reputation: 17848

Since you are using DevExpress you can use all the benefits of DevExpress MVVM Framework and their POCO-ViewModels:

using DevExpress.Mvvm.POCO;
//...
public class ListViewModel {
    public ObservableCollection<Contact> GridData { get; private set; }

    // mark the SelectedEntities property as virtual to be notified on initializing/replacing
    public virtual ObservableCollection<Contact> SelectedEntities { get; private set; }
    // unsubscribe the CollectionChanged event in changing-callback
    protected void OnSelectedEntitiesChanging() {
        if(SelectedEntities != null)
            SelectedEntities.CollectionChanged -= SelectedEntities_CollectionChanged;
    }
    // subscribe the CollectionChanged event in changed-callback
    protected void OnSelectedEntitiesChanged() {
        if(SelectedEntities != null)
            SelectedEntities.CollectionChanged += SelectedEntities_CollectionChanged;
        UpdateSelectedEntitiesDependencies();
    }
    void UpdateSelectedEntitiesDependencies() {
        // Raise INPC for dependent properties
        this.RaisePropertyChanged(x => x.IsSingeselect);
        this.RaisePropertyChanged(x => x.IsMultiSelect);
        // Raise INPC for dependent properties of child ViewModels
        foreach(var item in ContextMenuItems)
            item.RaisePropertyChanged(x => x.Enabled);
    }
    void SelectedEntities_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) {
        if(e.Action == NotifyCollectionChangedAction.Add || e.Action == NotifyCollectionChangedAction.Remove || e.Action == NotifyCollectionChangedAction.Reset)
            UpdateSelectedEntitiesDependencies();
    }
    public bool IsSingeselect { get { return SelectedEntities.Count == 1; } }
    public bool IsMultiSelect { get { return SelectedEntities.Count > 0; } }
    public ObservableCollection<MenuComandViewModel> ContextMenuItems { get; private set; }
}

public class MenuComandViewModel {
    public bool Enabled {
        get {
            var parentViewModel = this.GetParentViewModel<ListViewModel>();
            return parentViewModel.IsMultiSelect; // Some implementation
        }
    }
}

Then you can bind you bar items to the ContextMenuItems collection using the approach described in MVVM Support in DXBars, DXRibbon and GalleryControl help-article.

Upvotes: 1

Related Questions