簡體   English   中英

WPF 選項卡控件防止選項卡更改

[英]WPF Tab Control Prevent Tab Change

我正在嘗試為我的應用程序開發一個系統維護屏幕,其中我有幾個選項卡,每個選項卡代表不同的維護選項,即維護系統用戶等。 一旦用戶點擊編輯/新建以更改現有記錄,我想防止離開當前選項卡,直到用戶點擊保存或取消。

經過一些谷歌搜索后,我發現了一個鏈接http://joshsmithonwpf.wordpress.com/2009/09/04/how-to-prevent-a-tabitem-from-being-selected/這似乎解決了我的問題,或者我想。

我試過實現這個,但我的事件似乎從未發生過。 下面是我的 XAML。

<TabControl Name="tabControl">
    <TabItem Header="Users">
        <DockPanel>
            <GroupBox Header="Existing Users" Name="groupBox1" DockPanel.Dock="Top" Height="50">
                <StackPanel Orientation="Horizontal">
                    <Label Margin="3,3,0,0">User:</Label>
                    <ComboBox Width="100"  Height="21" Margin="3,3,0,0"></ComboBox>
                    <Button Width="50" Height="21" Margin="3,3,0,0" Name="btnUsersEdit" Click="btnUsersEdit_Click">Edit</Button>
                    <Button Width="50" Height="21" Margin="3,3,0,0" Name="btnUsersNew" Click="btnUsersNew_Click">New</Button>
                </StackPanel>
            </GroupBox>
            <GroupBox Header="User Information" Name="groupBox2">
                <Button Content="Cancel" Height="21" Name="btnCancel" Width="50" Click="btnCancel_Click" />
            </GroupBox>
        </DockPanel>
    </TabItem>
    <TabItem Header="User Groups">

    </TabItem>        
</TabControl>

這是我的代碼

public partial class SystemMaintenanceWindow : Window
{

    private enum TEditMode { emEdit, emNew, emBrowse }

    private TEditMode _EditMode = TEditMode.emBrowse;        

    private TEditMode EditMode
    {
        get { return _EditMode; }
        set 
        { 
            _EditMode = value; 
        }
    }        

    public SystemMaintenanceWindow()
    {
        InitializeComponent();

        var view = CollectionViewSource.GetDefaultView(tabControl.Items.SourceCollection);
        view.CurrentChanging += this.Items_CurrentChanging;
    }        

    void Items_CurrentChanging(object sender, CurrentChangingEventArgs e)
    {
        if ((e.IsCancelable) && (EditMode != TEditMode.emBrowse))
        {
            var item = ((ICollectionView)sender).CurrentItem;
            e.Cancel = true;
            tabControl.SelectedItem = item;

            MessageBox.Show("Please Save or Cancel your work first.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
        }
    }        

    private void btnUsersNew_Click(object sender, RoutedEventArgs e)
    {
        EditMode = TEditMode.emNew;
    }

    private void btnUsersEdit_Click(object sender, RoutedEventArgs e)
    {
        EditMode = TEditMode.emEdit;
    }

    private void btnCancel_Click(object sender, RoutedEventArgs e)
    {
        EditMode = TEditMode.emBrowse;
    }
}

如果我是愚蠢的,現在道歉,但對於我的生活,我無法鍛煉明白為什么當用戶在選項卡之間單擊時我的事件不會觸發。

感謝你的幫助。

埃姆林

我想出了一個適合我需求的解決方案。 似乎略微倒退,但與其他選項相比,我發現它看起來很漂亮。

基本上我保留當前tabIndex的私有變量和tabControl的“SelectionChanged”事件我正在進行一些檢查,如果用戶不處於瀏覽模式,則將tabControl.SelectedIndex設置回此值。

private void tabControl_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
    {
        if (e.OriginalSource == tabControl)
        {
            if (EditMode == TEditMode.emBrowse)
            {
                _TabItemIndex = tabControl.SelectedIndex;
            }
            else if (tabControl.SelectedIndex != _TabItemIndex) 
            {
                e.Handled = true;

                tabControl.SelectedIndex = _TabItemIndex;

                MessageBox.Show("Please Save or Cancel your work first.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }

        }
    }

我也在努力解決這個問題。 只需添加即可讓它工作

IsSynchronizedWithCurrentItem="True"

設置為TabControl。 之后就像一個魅力。

根據這篇文章

https://social.msdn.microsoft.com/Forums/vstudio/en-US/d8ac2677-b760-4388-a797-b39db84a7e0f/how-to-cancel-tabcontrolselectionchanged?forum=wpf

這對我有用:

<TabControl>
   <TabControl.Resources>
     <Style TargetType="TabItem">
        <EventSetter Event="PreviewMouseLeftButtonDown" 
            Handler="OnPreviewMouseLeftButtonDown"/>
     </Style>  
   </TabControl.Resources>
   <TabItem Header="Tab1"/>
   <TabItem Header="Tab2"/>
</TabControl>
private void OnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    if (e.Source is TabItem) //do not handle clicks on TabItem content but on TabItem itself
    {
        var vm = this.DataContext as MyViewModel;
        if (vm != null)
        {
            if (!vm.CanLeave())
            {
                e.Handled = true;
            }
        }
    }
}

或者自己實施......

public delegate void PreviewSelectionChangedEventHandler(object p_oSender, PreviewSelectionChangedEventArgs p_eEventArgs);

public class PreviewSelectionChangedEventArgs
{
    internal PreviewSelectionChangedEventArgs(IList p_lAddedItems, IList p_lRemovedItems)
    {
        this.AddedItems = p_lAddedItems;
        this.RemovedItems = p_lRemovedItems;
    }
    public bool Cancel { get; set; }
    public IList AddedItems { get; private set; }
    public IList RemovedItems { get; private set; }
}

public class TabControl2: TabControl
{
    public event PreviewSelectionChangedEventHandler PreviewSelectionChanged;

    private int? m_lLastSelectedIndex;

    protected override void OnSelectionChanged(SelectionChangedEventArgs e)
    {
        base.OnSelectionChanged(e);

        // déterminer si on doit annuler la sélection
        PreviewSelectionChangedEventArgs eEventArgs = new PreviewSelectionChangedEventArgs(e.AddedItems, e.RemovedItems);
        if (m_lLastSelectedIndex.HasValue)
            if (PreviewSelectionChanged != null)
                PreviewSelectionChanged(this, eEventArgs);

        // annuler (ou pas) la sélection
        if (eEventArgs.Cancel)
            this.SelectedIndex = m_lLastSelectedIndex.Value;
        else
            m_lLastSelectedIndex = this.SelectedIndex;
    }
}

Josh正在使用tab.ItemsSource 您正在使用tab.Items.SourceCollection 這可能是問題所在。

我開始掌握XAML所以我希望我沒有錯過你的觀點。 我遇到了同樣的問題,對我而言這是最好的。

在XAML中,我定義了一個切換ReadOnly狀態的Style

<!-- prevent the tab from being changed while editing or adding a physician -->
<Style BasedOn="{StaticResource {x:Type TabControl}}" 
        TargetType="{x:Type TabControl}" x:Key="InactivateTabControl">
    <!-- <Setter Property="IsEnabled" Value="True" /> -->
    <Style.Triggers>
        <DataTrigger Binding="{Binding PhysicianTypeTabAreLocked}" Value="False">
            <Setter Property="IsEnabled" Value="True" />
        </DataTrigger>
        <DataTrigger Binding="{Binding PhysicianTypeTabAreLocked}" Value="True">
            <Setter Property="IsEnabled" Value="False" />
        </DataTrigger>
    </Style.Triggers>
</Style>

<TabControl Grid.Row="1" Grid.Column="0" Margin="0, 10, 0, 0"
     x:Name="PhysicianTypesTabControl" 
     SelectedIndex="{Binding PhysicianTypeSelectedTabIndex, Mode=TwoWay}" 
     Style="{StaticResource InactivateTabControl}">

    <!-- rest here ....-->

 <TabControl/>

在viewmodel中我有一個屬性

    private EditingState _PhysicianEditingState;

    public EditingState PhysicianEditingState
    {
        get { return _PhysicianEditingState; }
        set
        {
            _PhysicianEditingState = value;

            PhysicianTypeTabAreLocked = (PhysicianEditingState != EditingState.NotEditing);
            NotifyPropertyChanged("PhysicianTypeTabAreLocked");
        }
    }

希望這可以幫助。

最終對我來說非常有效的是當我不希望用戶能夠 select 時禁用“TabItems”,然后在我也需要它們時啟用它們。

<TabControl IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Pages}" SelectedItem="{Binding SelectedPage}" TabStripPlacement="Left">
        <TabControl.Resources>
            <Style BasedOn="{StaticResource {x:Type TabItem}}" TargetType="TabItem">
                <Setter Property="IsEnabled" Value="{Binding IsEnabled}" />
            </Style>
        </TabControl.Resources>
        <TabControl.ItemTemplate>
            <DataTemplate>
                <Label Content="{Binding StepName}" Foreground="{DynamicResource TabActiveSelectedFont}" />
            </DataTemplate>
        </TabControl.ItemTemplate>
</TabControl>

這使我的視圖 model(在本例中為我的頁面)能夠確定何時允許用戶移動到下一頁。 因此,當他們完成當前頁面后,我將“啟用”下一頁,以便他們可以單擊它繼續。

您可以簡單地將 TabItems 的IsEnabled屬性設置為 false,這會阻止導航/激活但不會禁用選項卡的內容,直到滿足您的條件(保存/取消)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM