/// <summary>
 /// Adds a channel to the group.
 /// </summary>
 /// <param name="channel">The channel.</param>
 /// <returns><c>true</c> if the channel is added, <c>false</c> otherwise.</returns>
 public bool Add(MixChannel channel) =>
 Native.Mix_GroupChannel(channel.Index, Index);
 /// <summary>
 /// Adds a set of channels to the group.
 /// </summary>
 /// <param name="from">The first channel.</param>
 /// <param name="to">The last channel.</param>
 /// <returns><c>true</c> if the channels are added, <c>false</c> otherwise.</returns>
 public bool Add(MixChannel from, MixChannel to) =>
 Native.Mix_GroupChannels(from.Index, to.Index, Index);
        public SelectedItemsViewModel(MixChannel template, int index = 0) : base(index)
        {
            //Fill in our arrays so that they have enough elements using the template if it exists
            //This is lazy but might work
            if (template != null)
            {
                foreach (PropertyInfo p in template.GetType().GetProperties())
                {
                    if (typeof(INotifyCollectionChanged).IsAssignableFrom(p.PropertyType))
                    {
                        p.SetValue(this, p.GetValue(template));
                    }
                }
            }

            //Now we add change listners to our virtual parameters such that when modified by the GUI we can reflect those changes in the selection
            AddLocalPropertyChangeEventHandlers(this);
            LocalParameterDictionaryBuilder(this);

            //Whenever we change selection add and remove notifiers from the selected channels we are listning to for changes.
            //Additionally, we need to update our flattened reference dictionary of addressable references to the properties of the selection.
            SelectedChannels = new ObservableCollection <MixChannel>();
            SelectedChannels.CollectionChanged += (o, e) =>
            {
                //We need to listen for changes in the model (if the physical mixer hardware changes model values)
                if (e.Action == NotifyCollectionChangedAction.Add)
                {
                    // Subscribe each to PropertyChanged, using Item_PropertyChanged
                    if (e.NewItems == null)
                    {
                        return;
                    }

                    foreach (MixChannel m in e.NewItems)
                    {
                        //Rebuild refs
                        RemoteParameterDictionaryBuilder(m);
                        //Add new change listners
                        AddRemotePropertyChangedEventHandlers(m);
                    }

                    //Even though we are about to add property change delegates we still need to invoke the notification on all properties here to refelect the existing values of the new selection
                    dontPropagateToSelection = true;
                    InvokeAllLocalPropertyChangedEvents(this);
                    dontPropagateToSelection = false;
                }
                if (e.Action == NotifyCollectionChangedAction.Remove || e.Action == NotifyCollectionChangedAction.Reset)
                {
                    //Rebuild reference dictionary
                    selectedChannelsParametersFlattened.Clear();
                    foreach (MixChannel m in selectedChannels)
                    {
                        RemoteParameterDictionaryBuilder(m);
                    }

                    //TODO: This is always null which leaves unselected channels with orphaned change notifiers
                    if (e.OldItems != null)
                    {
                        foreach (MixChannel m in e.OldItems)
                        {
                            RemoveRemotePropertyChangedEventHandlers(m);
                        }
                    }

                    foreach (KeyValuePair <string, List <Parameter> > props in selectedChannelsParametersFlattened)
                    {
                        foreach (Parameter p in props.Value)
                        {
                            p.PropertyChanged -= (sender, a) => PropagatePropertyChangeToViewModel(sender, a, props.Key);//Probs won't work
                        }
                    }
                    dontPropagateToSelection = true;
                    InvokeAllLocalPropertyChangedEvents(this);
                    dontPropagateToSelection = false;
                }
            };
        }