Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /// <summary>
- /// Логика взаимодействия для TabPanel.xaml
- /// </summary>
- public partial class TabPanel : UserControl
- {
- public TabPanel()
- {
- InitializeComponent();
- SizeChanged += TabPanel_SizeChanged;
- KeyDown += TabPanel_KeyDown;
- }
- private void TabPanel_KeyDown(object sender, KeyEventArgs e)
- {
- if(e.KeyboardDevice.Modifiers == ModifierKeys.Shift && e.Key == Key.S)
- {
- ScrollInfo();
- }
- }
- private void TabPanel_SizeChanged(object sender, SizeChangedEventArgs e)
- {
- SetArrowsVisibility();
- }
- // активная вкладка
- private UserControl activeTab;
- public UserControl ActiveTab
- {
- get { return activeTab; }
- set { activeTab = value; }
- }
- // возврат текущего количества вкладок на ленте
- private int tabCount;
- public int TabCount
- {
- get
- {
- tabCount = tabContainer.Children.Count;
- return tabCount;
- }
- }
- public Action<UserControl> ActiveTabLastAction;
- public Action<UserControl> ActiveTabFirstAction;
- /* метод для пометки вкладки на ленте как активной через заполнение соответствующего поля
- * также отрабатывают два метода, переданных с делегатами, влияющих на состояние
- * вкладки, теряющей активный статус и
- * вкладки, приобретающей активный статус
- * например, стиль кнопки и т.п.
- * здесь методы в аргументах, и это предпочтительно
- */
- public void SetActiveTab(UserControl newActiveTab, Action<UserControl> ActiveTabLastAction, Action<UserControl> ActiveTabFirstAction)
- {
- if (ContainsTab(newActiveTab))
- {
- if (ActiveTab != null)
- {
- ActiveTabLastAction?.Invoke(ActiveTab);
- }
- ActiveTab = newActiveTab;
- ActiveTabFirstAction?.Invoke(ActiveTab);
- }
- }
- /* метод для пометки вкладки на ленте как активной через заполнение соответствующего поля
- * также отрабатывают два метода, переданных с делегатами, влияющих на состояние
- * вкладки, теряющей активный статус и
- * вкладки, приобретающей активный статус
- * здесь взяты методы из полей самого класса ленты с вкладками
- * присвоение происходит в конструкторе родительского окна или контрола с лентой вкладок
- */
- public void SetActiveTab(UserControl newActiveTab)
- {
- SetActiveTab(newActiveTab, ActiveTabLastAction, ActiveTabFirstAction);
- }
- /* метод для добавления новой вкладки на ленту
- */
- public UserControl AddNewTab(UserControl tab)
- {
- tabContainer.Children.Add(tab);
- tab.SizeChanged += Tab_SizeChanged;
- tab.MouseLeftButtonUp += SwipeOnPartialHide;
- SetArrowsVisibility();
- double sum = 0;
- double[] swipeSteps = GetSwipeSteps();
- for(int i = 0; i < swipeSteps.Length; i++)
- {
- sum += swipeSteps[i];
- }
- tabScroll.ScrollToHorizontalOffset(sum);
- return tab;
- }
- /* методя для удаления вкладки с ленты
- */
- public void RemoveTab(UserControl tab)
- {
- tab.SizeChanged -= Tab_SizeChanged;
- tabContainer.Children.Remove(tab);
- if (tab == activeTab) activeTab = null;
- SetArrowsVisibility();
- }
- /* данный метод-обработчик события изменения размера контрола
- * пришлось ввести так как ActualWidth вкладки
- * меняется не сразу. В тот момент, когда он должен быть известен
- * он всё ещё равняется нулю. Соответственно, метод отслеживающий
- * момент переполнения видимой области ленты вкладок неверно
- * определяет когда должны появиться кнопки навигации по ленте
- * опоздание на одну вкладку
- */
- private void Tab_SizeChanged(object sender, SizeChangedEventArgs e)
- {
- SetArrowsVisibility();
- UserControl tab = sender as UserControl;
- }
- /* метод для скрытия вкладки на ленте без удаления
- * хз пока зачем он нужен, больше похоже на древний артефакт
- */
- public void HideTab(UserControl tab)
- {
- tab.Visibility = Visibility.Collapsed;
- }
- /* получить вкладку из ленты по индексу
- */
- public UserControl GetTab(int index)
- {
- if(tabContainer.Children.Count > 0)
- {
- if(index < tabContainer.Children.Count) return tabContainer.Children[index] as UserControl;
- else
- {
- return null;
- }
- }
- else
- {
- return null;
- }
- }
- /* поскольку класс TabPanel является лишь интерфейсом для организации
- * элементов, может существовать внешний источник с элементами
- * и может быть ситуация, когда надо проводить есть ли элемент в ленте
- */
- public bool ContainsTab(UserControl tab)
- {
- return tabContainer.Children.Contains(tab);
- }
- /* получить индекс элемента
- * можно задавать как
- */
- public int GetTabIndex(UserControl tab)
- {
- return tabContainer.Children.IndexOf(tab);
- }
- /* определение является ли элемент активной вкладкой
- */
- public bool IsActiveTab(UserControl tabToCompare)
- {
- if (activeTab == null) return false;
- return activeTab == tabToCompare;
- }
- /* метод для получения общей суммарной ширины всех элементов в
- * ряду вкладок
- */
- private double GetTotalWidth()
- {
- double totalWidth = 0;
- foreach (UserControl item in tabContainer.Children)
- {
- totalWidth += item.ActualWidth;
- }
- return totalWidth;
- }
- /* свойство для возврата значения отступа на ScrollView назад
- * в зависимости от текущего отступа и длины вкладки
- */
- public double OffsetBack
- {
- get
- {
- double sum = 0;
- double[] swipePositions = GetSwipeSteps();
- for (int i = 0; i < swipePositions.Length; i++)
- {
- sum += swipePositions[i];
- if (sum >= tabScroll.HorizontalOffset)
- {
- return sum - swipePositions[i];
- }
- }
- return 0;
- }
- }
- /* свойство для возврата значения отступа ScrollView вперёд
- * в зависимости от текущего отступа и длины вкладок
- */
- public double OffsetForward
- {
- get
- {
- double sum = 0;
- double[] swipePositions = GetSwipeSteps();
- for (int i = 0; i < swipePositions.Length; i++)
- {
- sum += swipePositions[i];
- if (sum > tabScroll.HorizontalOffset)
- {
- return sum;
- }
- }
- return 0;
- }
- }
- /* получить список длин всех вкладок в ленте
- */
- private double[] GetSwipeSteps()
- {
- int index = 0;
- double[] swipePositions = new double[tabContainer.Children.Count];
- foreach (UserControl item in tabContainer.Children)
- {
- swipePositions[index] = item.ActualWidth;
- index++;
- }
- return swipePositions;
- }
- /* условие для видимости стрелок прокрутки вкладок
- * когда общая длина вкладок больше, чем видимая область ScrollView
- * стрелки появляются
- * и наоборот
- */
- public void SetArrowsVisibility()
- {
- if (GetTotalWidth() >= tabScroll.ActualWidth) SwipeArrowsVisible = true;
- else SwipeArrowsVisible = false;
- }
- /* сдвижка scrollview влево
- */
- private void LeftTabSwipe_Click(object sender, RoutedEventArgs e)
- {
- try
- {
- tabScroll.ScrollToHorizontalOffset(OffsetBack);
- }
- catch
- {
- }
- }
- /* сдвижка scrollview вправо
- */
- private void RightTabSwipe_Click(object sender, RoutedEventArgs e)
- {
- try
- {
- tabScroll.ScrollToHorizontalOffset(OffsetForward);
- }
- catch
- {
- }
- }
- private void SwipeOnPartialHide(object sender, MouseButtonEventArgs e)
- {
- UserControl tab = sender as UserControl;
- int index = GetTabIndex(tab);
- double[] swipeSteps = GetSwipeSteps();
- double sum = 0;
- for(int i = 0; i < swipeSteps.Length; i++)
- {
- sum += swipeSteps[i];
- if( i == index)
- {
- if (tabScroll.HorizontalOffset < sum && tabScroll.HorizontalOffset > sum - swipeSteps[i])
- tabScroll.ScrollToHorizontalOffset(sum - swipeSteps[i]);
- double offsetPlusWidth = tabScroll.HorizontalOffset + tabScroll.ActualWidth;
- if(offsetPlusWidth > sum - swipeSteps[i] && offsetPlusWidth < sum)
- {
- tabScroll.ScrollToHorizontalOffset(tabScroll.HorizontalOffset + (sum - offsetPlusWidth));
- }
- }
- }
- }
- #region test control methods
- private void ScrollInfo()
- {
- MessageBox.Show($"Total tab width = {GetTotalWidth()} \n " +
- $"{nameof(tabScroll.ActualWidth)} = {tabScroll.ActualWidth} \n " +
- $"{nameof(tabScroll.HorizontalOffset)} = {tabScroll.HorizontalOffset} \n " +
- //$"{nameof(currentSwipe)} = {currentSwipe} \n " +
- $"{nameof(tabScroll.ExtentWidth)} - {tabScroll.ExtentWidth} \n" +
- $"{nameof(tabScroll.ContentHorizontalOffset)} - {tabScroll.ContentHorizontalOffset} \n" +
- $"{nameof(tabScroll.ScrollableWidth)} = {tabScroll.ScrollableWidth} \n ");
- }
- #endregion
- }
Advertisement
Add Comment
Please, Sign In to add comment