IsActive bound to a "true" property causes crash when Contextual Tab Group is added

Ribbon for WPF Forum

Posted 7 years ago by Michael Mason - Lead Software Developer, UI Technologies, WDH
Version: 13.1.0580
Platform: .NET 4.0
Environment: Windows 7 (64-bit)
Avatar

I can define a class (let's call it "MyCtg") which derives from ContextualTabGroup, and bind its IsActive property to a dependency property in my view model. For example, I can bind it to a Boolean property called "IsCorrectDocType" like this: IsActive="{Binding IsCorrectDocType}"

I create an instance of this class and add it to the ribbon's ContextualTabGroups collection in code like this:

    var myCtg = new MyCtg();
    ribbon.ContextualTabGroups.Add(myCtg);

I get different behavior depending on whether the "IsCorrectDocType" property (i.e. the property that IsActive is bound to) is "True" or "False" at the time the object is added to the collection.

If "IsCorrectDocType" is "False" at the time I add the group to the collection, everything works correctly and the tab group appears and disappears as expected when I toggle "IsCorrectDocType" true and false.

However, if "IsCorrectDocType" is "True" at the time that I attempt to add the instance of the class to the ContextualTabGroups collection, I get the following exception:

InvalidOperationException was unhandled: Cannot change ObservableCollection during a CollectionChanged event.

The only way that I found to avoid this problem is to:

  1. Use BindingOperations.GetBinding to retrieve the IsActiveProperty's binding. If the binding is null, IsActive is not databound, and we can simply add the object to the ContextualTabGroups collection.
  2. Manually set the IsActive flag to its current state [i.e. myCtg.IsActive = myCtg.IsActive;], having the effect of removing the binding. It also works to set IsActive explicitly to either true or false.
  3. Add my ContextualTabGroup object to the ribbon's ContextualTabGroups collection.
  4. Restore the IsActiveProperty's binding using BindingOperations.SetBinding.

My Contextual Tab Group is very simple:

<ribbon:ContextualTabGroup x:Class="ActiproPlayground.MyCtg"
                           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                           xmlns:ribbon="http://schemas.actiprosoftware.com/winfx/xaml/ribbon"
                           Label="Contextual Tools"
                           IsActive="{Binding IsCorrectDocType}"
                           >
    <ribbon:Tab Label="XSD">
        <ribbon:Group Label="Demo">
            <ribbon:Button ImageSourceLarge="/Resources/Images/CloseTab32.png" Label="Close Contextual Tab" />
        </ribbon:Group>
    </ribbon:Tab>
</ribbon:ContextualTabGroup>

 And my view model is just as basic:

using System.Windows;
namespace ActiproPlayground
{
    public class MainWindowViewModel : DependencyObject
    {
        public bool IsCorrectDocType
        {
            get { return (bool)GetValue(IsCorrectDocTypeProperty); }
            set { SetValue(IsCorrectDocTypeProperty, value); }
        }
        public static readonly DependencyProperty IsCorrectDocTypeProperty = DependencyProperty.Register("IsCorrectDocType", typeof(bool), typeof(MainWindowViewModel));
    }
}

[Modified 7 years ago]

Comments (2)

Posted 7 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Michael,

We haven't seen anything like that happen before.  Can you please wrap up the minimal code needed to make this occur into a simple sample project and e-mail that to our support address?  That way we can debug it and see what's going on before the upcoming maintenance release comes out.  Please reference this post and rename the .zip file extensions so it doesn't get spam blocked.  Thanks!


Actipro Software Support

Answer - Posted 6 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Michael,

Thanks for the sample. The problem here is that adding the ContextualTabGroup is triggering a tabs collection update, but down the line in that process, an UpdateLayout is called so that the CTG can align itself properly with the tab layout. The UpdateLayout seems to trigger the binding to execute and that process ends up calling the tabs to rebind again. Since that happens within that outer process, the exception seems to fire.

We've altered code to fix the problem.  This change will be in the upcoming maintenance release.


Actipro Software Support

The latest build of this product (v2019.1 build 0683) was released 1 month ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.