Я реализовал систему вкладок, используя регионы Prism и Syncfusion TabControlExt. Кратко о системе: MainTabControlViewModel — это основная ViewModel, хранящая коллекцию вкладок. Объектами вкладки являются MainTabItemViewModel. При создании вкладки создается MainTabItemViewModel и принимает параметры. Поскольку на момент создания конструктора регион еще не зарегистрирован, я подписываюсь на событие _scopedRegionManager.Regions.CollectionChanged. Обработчик ищет регион _contentRegionName и переходит к нему с параметрами. Все работает, но правильно ли?
Я создал систему закрепления и открепления вкладок (у Syncfusion есть стандартное решение, но оно не работало должным образом). При срабатывании PinCommand, в зависимости от флага IsPinned элемента, элемент удаляется из коллекции и вставляется в нужное место. Проблема в том, что при вставке в нужное место Prism пытается перерегистрировать регион, который находится в ContentTemplate вкладки, что вызывает ошибку «Регион с данным именем уже зарегистрирован». Пробовал все это сделать через Tabs.Move, но тоже выдает ошибку, так как TabControlExt не поддерживает Move. Эта ошибка также возникает при перетаскивании, поскольку встроенная система перетаскивания вкладок, вероятно, также приводит к регистрации региона.
MainTabControlView.xaml:
MainTabControlViewModel.cs:
public sealed class MainTabControlViewModel : ViewModelBase, IMainTabControlViewModel
{
private const int TabRemoveDelay = 160;
private readonly IRegionManager _regionManager;
private ObservableCollection _tabs = [];
private MainTabItemViewModel _selectedTabItem = null!;
private int _pinnedTabsCount;
public ObservableCollection Tabs
{
get => _tabs;
set => SetProperty(ref _tabs, value);
}
public MainTabItemViewModel SelectedTabItem
{
get => _selectedTabItem;
set => SetProperty(ref _selectedTabItem, value);
}
// Proxied from MainTabViewModel commands
private readonly DelegateCommand _closeCommand;
private readonly DelegateCommand _closeAllCommand;
private readonly DelegateCommand _closeOtherCommand;
private readonly DelegateCommand _pinCommand;
public DelegateCommand TabOrderChangingCommand => new(OnTabOrderChangingCommandExecuted);
public MainTabControlViewModel(IRegionManager regionManager)
{
_regionManager = regionManager;
_closeCommand = new DelegateCommand(OnCloseCommandExecuted);
_closeAllCommand = new DelegateCommand(OnCloseAllCommandExecuted);
_closeOtherCommand = new DelegateCommand(OnCloseOtherCommandExecuted);
_pinCommand = new DelegateCommand(OnPinCommandExecuted);
}
private async void RemoveTab(MainTabItemViewModel oldTabItem)
{
oldTabItem.Hide();
await Task.Delay(TabRemoveDelay);
oldTabItem.RemoveContent();
Tabs.Remove(oldTabItem);
if (Tabs.Any() && SelectedTabItem == oldTabItem)
{
SelectedTabItem = Tabs.First();
}
}
private void OnCloseCommandExecuted(MainTabItemViewModel tabItem)
{
RemoveTab(tabItem);
}
private void OnCloseAllCommandExecuted()
{
foreach (var tab in Tabs.ToList())
{
RemoveTab(tab);
}
}
private void OnCloseOtherCommandExecuted(MainTabItemViewModel tabItemVm)
{
foreach (var tab in Tabs.ToList().Where(tab => tabItemVm != tab))
{
RemoveTab(tab);
}
}
private void OnPinCommandExecuted(MainTabItemViewModel tabItem)
{
if (tabItem.Pinned)
{
tabItem.Unpin();
_pinnedTabsCount--;
Tabs.Remove(tabItem);
Tabs.Insert(_pinnedTabsCount, tabItem);
}
else
{
tabItem.Pin();
Tabs.Remove(tabItem);
Tabs.Insert(0, tabItem);
_pinnedTabsCount++;
}
}
private void OnTabOrderChangingCommandExecuted(TabOrderChangingEventArgs e)
{
var draggedTab = Tabs.ElementAt(e.OldIndex);
if (draggedTab.Pinned)
{
//If move a pinned tab outside the unpinned area (NewIndex >= _pinnedTabsCount), cancel it.
if (e.NewIndex >= _pinnedTabsCount)
{
e.Cancel = true;
return;
}
}
else
{
// If an unpinned tab is attempted to be moved to a pinned position (NewIndex < _pinnedTabsCount), cancel.
if (e.NewIndex < _pinnedTabsCount)
{
e.Cancel = true;
return;
}
}
e.Cancel = false;
}
public void AddTab(string viewName, string title, INavigationParameters parameters)
{
var scopedRegionManager = _regionManager.CreateRegionManager();
var newTabItem = new MainTabItemViewModel(title, viewName, parameters, scopedRegionManager);
newTabItem.SetCommands(_closeCommand, _closeAllCommand, _closeOtherCommand, _pinCommand);
Tabs.Add(newTabItem);
}
MainTabItemViewModel.cs:
public sealed class MainTabItemViewModel : ViewModelBase
{
private string _title;
private bool _selected = true;
private bool _showed = true;
private bool _pinned;
private bool _navigated;
private IRegionManager _scopedRegionManager;
private string _contentRegionName;
private string _contentViewName;
private INavigationParameters _parameters;
public Guid Id = Guid.NewGuid();
public bool Showed
{
get => _showed;
set => SetProperty(ref _showed, value);
}
public bool Selected
{
get => _selected;
set => SetProperty(ref _selected, value);
}
public string Title
{
get => _title;
set => SetProperty(ref _title, value);
}
public bool Pinned
{
get => _pinned;
set => SetProperty(ref _pinned, value);
}
public IRegionManager ScopedRegionManager
{
get => _scopedRegionManager;
set => SetProperty(ref _scopedRegionManager, value);
}
public string ContentRegionName
{
get => _contentRegionName;
set => SetProperty(ref _contentRegionName, value);
}
public DelegateCommand? CloseCommand { [UsedImplicitly] get; private set; }
public DelegateCommand? CloseAllCommand { [UsedImplicitly] get; private set; }
public DelegateCommand? CloseOtherCommand { [UsedImplicitly] get; private set; }
public DelegateCommand? PinCommand { [UsedImplicitly] get; private set; }
public MainTabItemViewModel(string title, string contentViewName, INavigationParameters parameters, IRegionManager scopedRegionManager)
{
_title = title;
_contentViewName = contentViewName;
_parameters = parameters;
_scopedRegionManager = scopedRegionManager;
_contentRegionName = $"MainTabRegion_{Id}";
_scopedRegionManager.Regions.CollectionChanged += RegionsOnCollectionChanged;
}
private void RegionsOnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if(_navigated) return;
if (e is not { Action: NotifyCollectionChangedAction.Add, NewItems: not null }) return;
foreach (var region in e.NewItems.Cast())
{
if (region.Name != _contentRegionName) return;
_navigated = true;
_scopedRegionManager.RequestNavigate(_contentRegionName, _contentViewName, _parameters);
_scopedRegionManager.Regions.CollectionChanged -= RegionsOnCollectionChanged;
}
}
public void SetCommands(
DelegateCommand? closeCommand,
DelegateCommand? closeAllCommand,
DelegateCommand? closeOtherCommand,
DelegateCommand? pinCommand)
{
CloseCommand = closeCommand;
CloseAllCommand = closeAllCommand;
CloseOtherCommand = closeOtherCommand;
PinCommand = pinCommand;
}
public void Hide()
{
Showed = false;
}
public void Pin()
{
Pinned = true;
}
public void Unpin()
{
Pinned = false;
}
public void RemoveContent()
{
_scopedRegionManager.Regions[_contentRegionName].RemoveAll();
}
Подробнее здесь: https://stackoverflow.com/questions/798 ... tabcontrol
Перерегистрация региона Prism при закреплении вкладки в TabControl ⇐ C#
Место общения программистов C#
-
Anonymous
1763235740
Anonymous
Я реализовал систему вкладок, используя регионы Prism и Syncfusion TabControlExt. Кратко о системе: MainTabControlViewModel — это основная ViewModel, хранящая коллекцию вкладок. Объектами вкладки являются MainTabItemViewModel. При создании вкладки создается MainTabItemViewModel и принимает параметры. Поскольку на момент создания конструктора регион еще не зарегистрирован, я подписываюсь на событие _scopedRegionManager.Regions.CollectionChanged. Обработчик ищет регион _contentRegionName и переходит к нему с параметрами. Все работает, но правильно ли?
Я создал систему закрепления и открепления вкладок (у Syncfusion есть стандартное решение, но оно не работало должным образом). При срабатывании PinCommand, в зависимости от флага IsPinned элемента, элемент удаляется из коллекции и вставляется в нужное место. Проблема в том, что при вставке в нужное место Prism пытается перерегистрировать регион, который находится в ContentTemplate вкладки, что вызывает ошибку «Регион с данным именем уже зарегистрирован». Пробовал все это сделать через Tabs.Move, но тоже выдает ошибку, так как TabControlExt не поддерживает Move. Эта ошибка также возникает при перетаскивании, поскольку встроенная система перетаскивания вкладок, вероятно, также приводит к регистрации региона.
MainTabControlView.xaml:
MainTabControlViewModel.cs:
public sealed class MainTabControlViewModel : ViewModelBase, IMainTabControlViewModel
{
private const int TabRemoveDelay = 160;
private readonly IRegionManager _regionManager;
private ObservableCollection _tabs = [];
private MainTabItemViewModel _selectedTabItem = null!;
private int _pinnedTabsCount;
public ObservableCollection Tabs
{
get => _tabs;
set => SetProperty(ref _tabs, value);
}
public MainTabItemViewModel SelectedTabItem
{
get => _selectedTabItem;
set => SetProperty(ref _selectedTabItem, value);
}
// Proxied from MainTabViewModel commands
private readonly DelegateCommand _closeCommand;
private readonly DelegateCommand _closeAllCommand;
private readonly DelegateCommand _closeOtherCommand;
private readonly DelegateCommand _pinCommand;
public DelegateCommand TabOrderChangingCommand => new(OnTabOrderChangingCommandExecuted);
public MainTabControlViewModel(IRegionManager regionManager)
{
_regionManager = regionManager;
_closeCommand = new DelegateCommand(OnCloseCommandExecuted);
_closeAllCommand = new DelegateCommand(OnCloseAllCommandExecuted);
_closeOtherCommand = new DelegateCommand(OnCloseOtherCommandExecuted);
_pinCommand = new DelegateCommand(OnPinCommandExecuted);
}
private async void RemoveTab(MainTabItemViewModel oldTabItem)
{
oldTabItem.Hide();
await Task.Delay(TabRemoveDelay);
oldTabItem.RemoveContent();
Tabs.Remove(oldTabItem);
if (Tabs.Any() && SelectedTabItem == oldTabItem)
{
SelectedTabItem = Tabs.First();
}
}
private void OnCloseCommandExecuted(MainTabItemViewModel tabItem)
{
RemoveTab(tabItem);
}
private void OnCloseAllCommandExecuted()
{
foreach (var tab in Tabs.ToList())
{
RemoveTab(tab);
}
}
private void OnCloseOtherCommandExecuted(MainTabItemViewModel tabItemVm)
{
foreach (var tab in Tabs.ToList().Where(tab => tabItemVm != tab))
{
RemoveTab(tab);
}
}
private void OnPinCommandExecuted(MainTabItemViewModel tabItem)
{
if (tabItem.Pinned)
{
tabItem.Unpin();
_pinnedTabsCount--;
Tabs.Remove(tabItem);
Tabs.Insert(_pinnedTabsCount, tabItem);
}
else
{
tabItem.Pin();
Tabs.Remove(tabItem);
Tabs.Insert(0, tabItem);
_pinnedTabsCount++;
}
}
private void OnTabOrderChangingCommandExecuted(TabOrderChangingEventArgs e)
{
var draggedTab = Tabs.ElementAt(e.OldIndex);
if (draggedTab.Pinned)
{
//If move a pinned tab outside the unpinned area (NewIndex >= _pinnedTabsCount), cancel it.
if (e.NewIndex >= _pinnedTabsCount)
{
e.Cancel = true;
return;
}
}
else
{
// If an unpinned tab is attempted to be moved to a pinned position (NewIndex < _pinnedTabsCount), cancel.
if (e.NewIndex < _pinnedTabsCount)
{
e.Cancel = true;
return;
}
}
e.Cancel = false;
}
public void AddTab(string viewName, string title, INavigationParameters parameters)
{
var scopedRegionManager = _regionManager.CreateRegionManager();
var newTabItem = new MainTabItemViewModel(title, viewName, parameters, scopedRegionManager);
newTabItem.SetCommands(_closeCommand, _closeAllCommand, _closeOtherCommand, _pinCommand);
Tabs.Add(newTabItem);
}
MainTabItemViewModel.cs:
public sealed class MainTabItemViewModel : ViewModelBase
{
private string _title;
private bool _selected = true;
private bool _showed = true;
private bool _pinned;
private bool _navigated;
private IRegionManager _scopedRegionManager;
private string _contentRegionName;
private string _contentViewName;
private INavigationParameters _parameters;
public Guid Id = Guid.NewGuid();
public bool Showed
{
get => _showed;
set => SetProperty(ref _showed, value);
}
public bool Selected
{
get => _selected;
set => SetProperty(ref _selected, value);
}
public string Title
{
get => _title;
set => SetProperty(ref _title, value);
}
public bool Pinned
{
get => _pinned;
set => SetProperty(ref _pinned, value);
}
public IRegionManager ScopedRegionManager
{
get => _scopedRegionManager;
set => SetProperty(ref _scopedRegionManager, value);
}
public string ContentRegionName
{
get => _contentRegionName;
set => SetProperty(ref _contentRegionName, value);
}
public DelegateCommand? CloseCommand { [UsedImplicitly] get; private set; }
public DelegateCommand? CloseAllCommand { [UsedImplicitly] get; private set; }
public DelegateCommand? CloseOtherCommand { [UsedImplicitly] get; private set; }
public DelegateCommand? PinCommand { [UsedImplicitly] get; private set; }
public MainTabItemViewModel(string title, string contentViewName, INavigationParameters parameters, IRegionManager scopedRegionManager)
{
_title = title;
_contentViewName = contentViewName;
_parameters = parameters;
_scopedRegionManager = scopedRegionManager;
_contentRegionName = $"MainTabRegion_{Id}";
_scopedRegionManager.Regions.CollectionChanged += RegionsOnCollectionChanged;
}
private void RegionsOnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if(_navigated) return;
if (e is not { Action: NotifyCollectionChangedAction.Add, NewItems: not null }) return;
foreach (var region in e.NewItems.Cast())
{
if (region.Name != _contentRegionName) return;
_navigated = true;
_scopedRegionManager.RequestNavigate(_contentRegionName, _contentViewName, _parameters);
_scopedRegionManager.Regions.CollectionChanged -= RegionsOnCollectionChanged;
}
}
public void SetCommands(
DelegateCommand? closeCommand,
DelegateCommand? closeAllCommand,
DelegateCommand? closeOtherCommand,
DelegateCommand? pinCommand)
{
CloseCommand = closeCommand;
CloseAllCommand = closeAllCommand;
CloseOtherCommand = closeOtherCommand;
PinCommand = pinCommand;
}
public void Hide()
{
Showed = false;
}
public void Pin()
{
Pinned = true;
}
public void Unpin()
{
Pinned = false;
}
public void RemoveContent()
{
_scopedRegionManager.Regions[_contentRegionName].RemoveAll();
}
Подробнее здесь: [url]https://stackoverflow.com/questions/79811587/re-registering-a-prism-region-when-a-pin-tab-in-tabcontrol[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия