WPF Tab Control запретить изменение вкладки
Я пытаюсь разработать экран обслуживания системы для моего приложения, в котором у меня есть несколько вкладок, каждая из которых представляет собой другой вариант обслуживания, т. е. поддерживает пользователей системы и т. д. Как только пользователь нажимает "изменить/создать", чтобы изменить существующую запись, я хочу запретить переход от текущей вкладки до тех пор, пока пользователь не нажмет "сохранить" или "отменить".
после некоторого googling я нашел ссылку http://joshsmithonwpf.wordpress.com/2009/09/04/how-to-prevent-a-tabitem-from-being-selected/
6 ответов
Я придумал решение, которое соответствует моим потребностям. Кажется немного назад, но по сравнению с другими вариантами, которые я нашел, кажется приятным и аккуратным.
в основном я сохраняю закрытую переменную текущего tabIndex и на событии "SelectionChanged" tabControl я делаю некоторые проверки и устанавливаю 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. После этого сработало как по волшебству.
Джош используя tab.ItemsSource
. Вы используете tab.Items.SourceCollection
. Это может быть проблемой.
или выполнять его самостоятельно...
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;
}
}
согласно этому сообщению
это сработало для меня:
<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;
}
}
}
}
Я начинаю понимать XAML, поэтому надеюсь, что я не пропустил вашу точку зрения. У меня была такая же проблема, и для меня это сработало лучше всего.
в XAML я определяю стиль, который переключает состояние ReadOnly
<!-- 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");
}
}
надеюсь, что это помогает.