This is a migrated thread and some comments may be shown as answers.

Prism and RadDocking

0 Answers 55 Views
Docking
This is a migrated thread and some comments may be shown as answers.
Simone
Top achievements
Rank 1
Simone asked on 01 Aug 2019, 04:48 PM

Hi,
I've create an application with prism and RadDocking. My problem is that the controls in the rad panes don't lose the focus when I clicked in another rad pane.
This happen only after the first loading of layout. In my case, I resolve the instance of the module in base of the serialization tag (to have only an instance of the module) and add to the region the view (to have the list of the view present in the regions, but in the DockingPanesFactory I skip the add of the pane, because it's already present in the docking).

I've also tried to use Region.Activate and Deactivate when the IsActive property changed.

Do you have any suggestions?

Justin
Top achievements
Rank 2
Iron
commented on 20 Sep 2023, 07:21 PM

You likely solved this, but I'm posting for anyone in the future who needs this functionality. I'm not sure if this solves the 'doesn't lose focus' that you said. What this will do is set IActiveAware.IsActive on the view/viewmodel when clicking in around the different panes in the dock.

This was tricky, but I found a solution. I started with the ShellPrism8 project in the Telerik Github repo: xaml-sdk/Docking/ShellPrism8 at master · telerik/xaml-sdk (github.com).

I'm pretty certain that DockActivationRegionBehavior.cs does nothing. Delete it. Create a new class called DockActivePaneChanagedBehavior.

The meat of the behavior lies in HostControl_ActivePaneChanged(). Simply activate the new pane and deactivate the old pane.

/// <summary>
/// Defines the attached behavior that makes sure that when clicking out of a Docking Pane the <see cref="Prism.IActiveAware.IsActive"/> property is automatically set.
/// <remarks>
/// 
/// This code was derived from Prism.Navigation.Regions.Behaviors.SelectorItemsSourceSyncBehavior.
/// </remarks>
/// </summary>
public class DockActivePaneChanagedBehavior : RegionBehavior, IDisposable
{
    /// <summary>
    /// Name that identifies the DockActivePaneSyncBehavior behavior in a collection of RegionsBehaviors. 
    /// </summary>
    public static readonly string BehaviorKey = "DockActivePaneChangedBehavior";

    /// <summary>
    /// Gets or sets RadDocking that the <see cref="IRegion"/> is attached to.
    /// </summary>
    /// <value>
    /// A RadDocking that the <see cref="IRegion"/> is attached to.
    /// </value>
    public RadDocking HostControl { get; set; }

    public void Dispose()
    {
        if (HostControl != null)
            HostControl.ActivePaneChanged -= HostControl_ActivePaneChanged;
    }

    /// <summary>
    /// Starts to monitor the <see cref="RadDocking"/> for clicking out of Panes.
    /// </summary>
    protected override void OnAttach()
    {
        if(HostControl != null)
            HostControl.ActivePaneChanged += HostControl_ActivePaneChanged;
    }

    /// <summary>
    /// Called when the active pane is changed to (de)activate the views which ultimately sets <see cref="Prism.IActiveAware.IsActive"/> accordingly which ends up calling RegionActiveAwareBehavior.OnCollectionChanged.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e">Contains both the old and new view.</param>
    private void HostControl_ActivePaneChanged(object? sender, Telerik.Windows.Controls.Docking.ActivePangeChangedEventArgs e)
    {
        try
        {
            foreach (var view in Region.ActiveViews)
            {
                Region.Deactivate(view);
            }

            if (e.OldPane is IActiveAware)
            {
                if (Region.Views.Contains(e.OldPane))
                    Region.Deactivate(e.OldPane);
            }
            if (e.NewPane is IActiveAware)
            {
                if (Region.Views.Contains(e.NewPane))
                    Region.Activate(e.NewPane);
            }
        }
        catch(Exception) { }
    }
}


 

Then, update DockingRegionAdapter to override AttachBehaviors.

public class DockingRegionAdapter : RegionAdapterBase<RadDocking>
{
    private readonly IRegionBehaviorFactory factory;

    /// <summary>
    /// This is a singleton.
    /// </summary>
    public DockingRegionAdapter(IRegionBehaviorFactory regionBehaviorFactory)
        : base(regionBehaviorFactory)
    {
        factory = regionBehaviorFactory;
    }

    protected override void Adapt(IRegion region, RadDocking regionTarget)
    {
        regionTarget.PanesSource = region.Views;
    }

    protected override IRegion CreateRegion()
    {
        var region = new Region();

        return region;
    }

    protected override void AttachBehaviors(IRegion region, RadDocking regionTarget)
    {
        if (region == null)
            throw new ArgumentNullException(nameof(region));

        // Add the behavior that syncs the items source items with the rest of the items
        region.Behaviors.Add(DockActivePaneChanagedBehavior.BehaviorKey, new DockActivePaneChanagedBehavior()
        {
            HostControl = regionTarget
        });

        base.AttachBehaviors(region, regionTarget);
    }
}

 

You might need to add the new behavior if it's missing in ConfigureDefaultRegionBehaviors in application startup. Not sure if this is necessary since you add it to the region when attaching in DockingRegionAdapter.

Martin Ivanov
Telerik team
commented on 21 Sep 2023, 08:27 AM

Hey Justin, thanks for sharing your solution!

No answers yet. Maybe you can help?

Tags
Docking
Asked by
Simone
Top achievements
Rank 1
Share this question
or