当用户尝试移至新选项卡时,我需要检测到脏页面,并为用户提供取消移出当前选项卡的选项。当我不需要询问用户时,我可以使它工作,但是显示消息框会破坏功能。我提供了一个显示问题的简单应用程序。抱歉,它在VB中,但这就是我们在这里使用的。
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ChangeTab"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<TabControl SelectedIndex="{Binding SelectedIndex}" Initialized="TabControl_Initialized" IsSynchronizedWithCurrentItem="True">
<TabItem Header="Tab 1">
<TextBlock Text="Content 1"/>
</TabItem>
<TabItem Header="Tab 2">
<StackPanel>
<TextBlock Text="Content 2"/>
<CheckBox Content="Locked" IsChecked="{Binding IsChecked}"/>
</StackPanel>
</TabItem>
</TabControl>
</Window>
Imports System.ComponentModel
Imports System.Windows.Threading
Class MainWindow
Implements INotifyPropertyChanged
Dim tc As TabControl
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Public Function SetProperty(Of T)(ByRef storage As T, value As T, PropertyName As String) As Boolean
If Object.Equals(storage, value) Then Return False
storage = value
NotifyPropertyChanged(PropertyName)
Return True
End Function
Public Sub NotifyPropertyChanged(ByVal propertyName As String)
RaiseEvent PropertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(propertyName))
End Sub
Private _IsChecked As Boolean
Public Property IsChecked As Boolean
Get
Return _IsChecked
End Get
Set(value As Boolean)
SetProperty(_IsChecked, value, "IsChecked")
End Set
End Property
Private _SelectedIndex As Integer
Public Property SelectedIndex As Integer
Get
Return _SelectedIndex
End Get
Set(value As Integer)
SetProperty(_SelectedIndex, value, "SelectedIndex")
End Set
End Property
Private Sub TabControl_Initialized(sender As Object, e As EventArgs)
tc = DirectCast(sender, TabControl)
AddHandler tc.Items.CurrentChanging, AddressOf Items_CurrentChanging
End Sub
Private Sub Items_CurrentChanging(sender As Object, e As CurrentChangingEventArgs)
Dim Result As MessageBoxResult
If SelectedIndex = 0 And IsChecked Then
Result = MessageBox.Show("Do you want to leave this tab?", "Leave", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No, MessageBoxOptions.ServiceNotification)
If Result = MessageBoxResult.No Then
e.Cancel = True
tc.SelectedItem = DirectCast(sender, ICollectionView).CurrentItem
End If
End If
End Sub
End Class
如果您运行此应用并按照以下步骤操作,则会发现标签页控件停止响应标签页更改。
1. Click TAB 2 (we move to TAB 2)
2. Check the Locked checkbox
3. Click TAB 1
4. Respond NO to the popup (we stay on TAB 2)
5. Click TAB 1 again
6. Response YES to the popup (we return to TAB 1)
7. Click TAB 2 again (we move to TAB 2)
8. Click on TAB 1
9. Response NO to the popup (we stay on TAB 2)
10. Click on TAB 1 again -- nothing happens!
注意:如果清除并选中“锁定”复选框,则功能将返回。 如果在Items_CurrentChanging中放置一个断点,则一切正常。当然,这是一个线程问题-谁能告诉我哪里出了问题,更重要的是,如何解决它?
谢谢
答案 0 :(得分:0)
似乎没有引发Items_CurrentChanging事件,因为我单击的选项卡仍然具有焦点(即使它不是当前项目)。我不知道为什么我们必须经历两次迭代才能看到问题。解决方案是在设置SelectedIndex之后添加一行代码。这会将焦点重新设置到我们没有离开的标签上。
Dispatcher.BeginInvoke(Sub() DirectCast(tc.SelectedItem, UIElement).Focus())
如果有人可以照亮这里发生的事情,我将非常感激。