如何取消 WPF TabControl 中的选项卡更改

问题描述 投票:0回答:6
c# wpf tabcontrol
6个回答
1
投票

这个解决方案来自web.archive

似乎与

一起工作得很好
<TabControl ... yournamespace:SelectorAttachedProperties.IsSynchronizedWithCurrentItemFixEnabled="True" .../>

private void OnCurrentChanging(object sender, CurrentChangingEventArgs e)
{                   
    if (MessageBox.Show("Change tab?", "Message", MessageBoxButton.YesNo) == MessageBoxResult.No)
    {
        e.Cancel = true;                    
    }                     
}



public static class SelectorAttachedProperties
{
    private static Type _ownerType = typeof(SelectorAttachedProperties);
 
    #region IsSynchronizedWithCurrentItemFixEnabled
 
    public static readonly DependencyProperty IsSynchronizedWithCurrentItemFixEnabledProperty =
        DependencyProperty.RegisterAttached("IsSynchronizedWithCurrentItemFixEnabled", typeof(bool), _ownerType,
        new PropertyMetadata(false, OnIsSynchronizedWithCurrentItemFixEnabledChanged));
 
    public static bool GetIsSynchronizedWithCurrentItemFixEnabled(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsSynchronizedWithCurrentItemFixEnabledProperty);
    }
 
    public static void SetIsSynchronizedWithCurrentItemFixEnabled(DependencyObject obj, bool value)
    {
        obj.SetValue(IsSynchronizedWithCurrentItemFixEnabledProperty, value);
    }
 
    private static void OnIsSynchronizedWithCurrentItemFixEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Selector selector = d as Selector;
        if (selector == null || !(e.OldValue is bool && e.NewValue is bool) || e.OldValue == e.NewValue)
            return;
 
        bool enforceCurrentItemSync = (bool)e.NewValue;
        ICollectionView collectionView = null;
 
        EventHandler itemsSourceChangedHandler = null;
        itemsSourceChangedHandler = delegate
        {
            collectionView = selector.ItemsSource as ICollectionView;
            if (collectionView == null)
                collectionView = CollectionViewSource.GetDefaultView(selector);
        };
 
        SelectionChangedEventHandler selectionChangedHanlder = null;
        selectionChangedHanlder = delegate
        {
            if (collectionView == null)
                return;
 
            if (selector.IsSynchronizedWithCurrentItem == true && selector.SelectedItem != collectionView.CurrentItem)
            {
                selector.IsSynchronizedWithCurrentItem = false;
                selector.SelectedItem = collectionView.CurrentItem;
                selector.IsSynchronizedWithCurrentItem = true;
            }
        };
 
        if (enforceCurrentItemSync)
        {
            TypeDescriptor.GetProperties(selector)["ItemsSource"].AddValueChanged(selector, itemsSourceChangedHandler);
            selector.SelectionChanged += selectionChangedHanlder;
        }
        else
        {
            TypeDescriptor.GetProperties(selector)["ItemsSource"].RemoveValueChanged(selector, itemsSourceChangedHandler);
            selector.SelectionChanged -= selectionChangedHanlder;
        }
    }
 
    #endregion IsSynchronizedWithCurrentItemFixEnabled
}

1
投票

出于某种原因,添加 TabControl.Focus() 可以解决问题:

private void OnCurrentChanged(object sender, EventArgs e)
{
    if (!_cancelTabChange)
    {
        //Update current tab property, if user did not cancel transition
        CurrentTab = (string)Tabs.CurrentItem;
    }
    else
    {
        //navigate back to current tab otherwise
        Dispatcher.BeginInvoke(new Action(() => 
        {
            Tabs.MoveCurrentTo(CurrentTab);
            TabControl.Focus();
        }));
    }
}

我仍然不知道地球上到底发生了什么。所以我很乐意接受这个答案,这对这个问题有所启发。


1
投票

在 tabControl_SelectionChanged 事件处理程序中:

if (e.OriginalSource == tabControl) //if this event fired from your tabControl
            {
                e.Handled = true;

                if (!forbiddenPage.IsSelected)  //User leaving the tab
                {
                    if (forbiddenTest())
                    {
                        forbiddenPage.IsSelected = true;
                        MessageBox.Show("you must not leave this page");
                    }
             }

注意设置forbiddenPage.IsSelected = true会导致循环,你重新进入 这个事件处理程序。然而,这次我们退出,因为所选页面是禁止页面。


0
投票
private void MainTabControl_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (ReasonBecauseLeaveTabItemIsForbidden)
        {
            if (MainTabControl.SelectedIndex == IndexOfTabItem)
            {
                MessageBox.Show(SomeMessageWhyLeaveTabItemIsForbidden);
            }
            MainTabControl.SelectedIndex = IndexOfTabItem;
        }
    }

IndexOfTabItem - 因离开而禁用的 TabItem 的索引。


-1
投票

必须服从的人要求应用程序询问用户是否要离开页面,因此这里是稍微更改的代码:

    private Object _selectedTab;

    public Object SelectedTab
    {
        get
        {
            return _selectedTab;
        }
        set
        {
            if (
                  !(_selectedTab is ADR_Scanner.ViewModel.ConfigurationViewModel) || 
                  !_configurationViewModel.HasChanged ||
                  (System.Windows.Forms.MessageBox.Show("Are you sure you want to leave this page without saving the configuration changes", ADR_Scanner.App.Current.MainWindow.Title, System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Error) == System.Windows.Forms.DialogResult.Yes)
                )
            {
                _selectedTab = value;
            }
            OnPropertyChanged("SelectedTab");
        }
    }

我认为这个小改动几乎可以满足您的需求。


-2
投票

有一个更简单的解决方案。向 XAML 中的选定项添加绑定:

    <TabControl SelectedItem="{Binding SelectedTab}" ... 

然后在视图模型中:

    private Object _selectedTab;

    public Object SelectedTab
    {
        get
        {
            return _selectedTab;
        }
        set
        {
            if (_selectedTab is ADR_Scanner.ViewModel.ConfigurationViewModel && _configurationViewModel.HasChanged)
            {
                System.Windows.Forms.MessageBox.Show("Please save the configuration changes", ADR_Scanner.App.ResourceAssembly.GetName().Name, System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
            }
            else
            {
                _selectedTab = value;
            }
            OnPropertyChanged("SelectedTab");
        }
    }

显然,您将 ADR_Scanner.ViewModel.ConfigurationViewModel 替换为您自己的视图模型类。最后确保在构造函数中初始化 _selectedTab,否则 TabControl 将没有初始选择。

© www.soinside.com 2019 - 2024. All rights reserved.