Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sample Tab Control Adapter #110

Draft
wants to merge 7 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion samples/SampleMvvmApp/App.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ protected override void RegisterTypes(IContainerRegistry containerRegistry)
// Views - Region Navigation
containerRegistry.RegisterForNavigation<DashboardView, DashboardViewModel>();
containerRegistry.RegisterForNavigation<SettingsView, SettingsViewModel>();
containerRegistry.RegisterForNavigation<SubSettingsView, SubSettingsViewModel>();
containerRegistry.RegisterForNavigation<SettingsSubView, SettingsSubViewModel>();
}

/// <summary>Register optional modules in the catalog.</summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@

namespace SampleMvvmApp.ViewModels
{
public class SubSettingsViewModel : ViewModelBase
public class SettingsSubViewModel : ViewModelBase
{
private readonly IRegionManager _regionManager;
private IRegionNavigationJournal? _journal;
private string _messageText = string.Empty;
private string _messageNumber = string.Empty;

public SubSettingsViewModel(IRegionManager regionManager)
public SettingsSubViewModel(IRegionManager regionManager)
{
_regionManager = regionManager;

Expand Down
2 changes: 1 addition & 1 deletion samples/SampleMvvmApp/ViewModels/SettingsViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public SettingsViewModel(IRegionManager regionManager)

_regionManager.RequestNavigate(
RegionNames.ContentRegion,
nameof(SubSettingsView),
nameof(SettingsSubView),
navParams);
});

Expand Down
11 changes: 11 additions & 0 deletions samples/SampleMvvmApp/ViewModels/TabControlViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SampleMvvmApp.ViewModels;

public class TabControlViewModel
{
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<UserControl xmlns="https://github.com/avaloniaui"
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="350"
x:Class="SampleMvvmApp.Views.SubSettingsView">
x:Class="SampleMvvmApp.Views.SettingsSubView">
<DockPanel>
<StackPanel DockPanel.Dock="Top" Spacing="5">
<Grid Background="LightGray" ColumnDefinitions="Auto, *">
Expand Down
11 changes: 11 additions & 0 deletions samples/SampleMvvmApp/Views/SettingsSubView.axaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Avalonia.Controls;

namespace SampleMvvmApp.Views;

public partial class SettingsSubView : UserControl
{
public SettingsSubView()
{
InitializeComponent();
}
}
11 changes: 0 additions & 11 deletions samples/SampleMvvmApp/Views/SubSettingsView.axaml.cs

This file was deleted.

8 changes: 8 additions & 0 deletions samples/SampleMvvmApp/Views/TabControlView.axaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="SampleMvvmApp.Views.TabControlView">
Welcome to Avalonia!
</UserControl>
11 changes: 11 additions & 0 deletions samples/SampleMvvmApp/Views/TabControlView.axaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Avalonia.Controls;

namespace SampleMvvmApp.Views;

public partial class TabControlView : UserControl
{
public TabControlView()
{
InitializeComponent();
}
}
3 changes: 1 addition & 2 deletions src/Prism.Avalonia/Regions/ContentControlRegionAdapter.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Controls;
using Prism.Properties;
using System;
using System.Collections.Specialized;
Expand Down
36 changes: 36 additions & 0 deletions src/Prism.Avalonia/Regions/GridRegionAdapter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using Avalonia.Controls;

namespace Prism.Regions
{
public class GridRegionAdapter : RegionAdapterBase<Grid>
{
public GridRegionAdapter(IRegionBehaviorFactory regionBehaviorFactory)
: base(regionBehaviorFactory)
{
}

protected override void Adapt(IRegion region, Grid regionTarget)
{
region.Views.CollectionChanged += (sender, e) =>
{
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
foreach (Control item in e.NewItems)
{
regionTarget.Children.Add(item);
}
}

if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
{
foreach (Control item in e.OldItems)
{
regionTarget.Children.Remove(item);
}
}
};
}

protected override IRegion CreateRegion() => new SingleActiveRegion() { };
}
}
38 changes: 38 additions & 0 deletions src/Prism.Avalonia/Regions/StackPanelRegionAdapter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using Avalonia.Controls;

namespace Prism.Regions
{
public class StackPanelRegionAdapter : RegionAdapterBase<StackPanel>
{
public StackPanelRegionAdapter(IRegionBehaviorFactory regionBehaviorFactory)
: base(regionBehaviorFactory)
{
}

protected override void Adapt(IRegion region, StackPanel regionTarget)
{
region.Views.CollectionChanged += (sender, e) =>
{
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
foreach (Control item in e.NewItems)
{
if (e.NewItems != null)
regionTarget.Children.Add(item);
}
}

if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
{
foreach (Control item in e.OldItems)
{
if (e.OldItems != null)
regionTarget.Children.Remove(item);
}
}
};
}

protected override IRegion CreateRegion() => new SingleActiveRegion() { };
}
}
96 changes: 96 additions & 0 deletions src/Prism.Avalonia/Regions/TabControlRegionAdapter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
using System;
using System.Collections.Specialized;
using System.Linq;
using Avalonia.Controls;

namespace Prism.Regions
{
/// <summary>
/// Adapts TabControl's TabItem (content control) to a Prism Region
/// so that you can hook Regions to the TabControl in XAML.
/// <code><![CDATA[
/// <TabControl prism:RegionManager.RegionName="MailTabRegion" />
/// ]]></code>
///
/// Tab Control Adapter for hooking tabs to regions (UserControl as a TabItem)
/// * Tab Header: UserControl's `Tag` property
/// </summary>
public class TabControlRegionAdapter : RegionAdapterBase<TabControl>
{
public TabControlRegionAdapter(IRegionBehaviorFactory regionBehaviorFactory) : base(regionBehaviorFactory)
{
}

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

if (regionTarget == null)
throw new ArgumentNullException(nameof(regionTarget));

// Detect a Tab Selection Changed
regionTarget.SelectionChanged += (object s, SelectionChangedEventArgs e) =>
{
// The view navigating away from
foreach (var item in e.RemovedItems)
{
// NOTE: The selected item isn't always a TabItem, if the region contains
// a ListBox, it's SelecitonChange gets picked up.
TargetSelectionChanged("Deactivating", item);
//// region.Deactivate(item);
}

// The view navigating to
foreach (var item in e.AddedItems)
{
TargetSelectionChanged("Activating", item);
////region.Activate(item);
}
};

// Detect when a TabItem has been added/removed to the TabControl
region.Views.CollectionChanged += (s, e) =>
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
foreach (UserControl item in e.NewItems)
{
var items = regionTarget.Items.Cast<TabItem>().ToList();
items.Add(new TabItem { Header = item.Tag, Content = item });
regionTarget.ItemsSource = items;
}
}
else if (e.Action == NotifyCollectionChangedAction.Remove)
{
foreach (UserControl item in e.OldItems)
{
var tabToDelete = regionTarget.Items.OfType<TabItem>().FirstOrDefault(n => n.Content == item);

// regionTarget.Items.Remove(tabToDelete); // WPF
var items = regionTarget.Items.Cast<TabItem>().ToList();
items.Remove(tabToDelete);
regionTarget.ItemsSource = items;
}
}
};
}

/// <summary>
/// AllActiveRegion - Can have multiple active views at the same time (i.e. multi-window views)
/// SingleActiveRegion - There is only one view active at a time. (i.e. Tab)
/// </summary>
/// <returns>Region</returns>
protected override IRegion CreateRegion() => new SingleActiveRegion();

private void TargetSelectionChanged(string changeAction, object itemChanged)
{
// The selected item isn't always a TabItem.
// In some cases, it could be the Region's ListBox item

TabItem item = itemChanged as TabItem;
if (item is null)
return;
}
}
}