نظرة عامة حول التركيز
في WPF يوجد مفهومين رئيسين متعلقين بالتركيز: تركيز لوحة المفاتيح و تركيز المنطقية. يشير تركيز لوحة المفاتيح إلى العنصر الذي يتلقى إدخال لوحة المفاتيح و تركيز المنطقية يشير إلى العنصر الذي عليه التركيز في نطاق تركيز. تتم مناقشة هذه المفاهيم بالتفصيل في هذه النظرة العامة. فهم الاختلاف في هذه المفاهيم مهم لإنشاء التطبيقات المعقدة التي تحتوي على مناطق متعددة حيث يمكن الحصول على التركيز.
الفئات الرئيسية المشاركة في إدارة التركيز هم فئة Keyboard, فئة FocusManager وفئات عناصر الأساس مثل UIElement و ContentElement. للحصول على معلومات إضافية حول العناصر الأساسية راجع نظرة عامة حول العناصر الأساسية.
فئة Keyboard تهتم بشكل أساسي بتركيز لوحة المفاتيح و FocusManager يهتم بشكل أساسي بتركيز المنطقية ولكن هذا ليس تمييز مطلق. العنصر الذي لديه تركيز لوحة المفاتيح سيكون أيضاً لديه تركيز المنطقية ولكن العنصر الذي لديه لتركيز المنطقية ليس بالضرورة أن يكون لديه تركيز لوحة المفاتيح. هذا واضح عند استخدام فئة Keyboard لتعيين العنصر الذي لديه تركيز لوحة المفاتيح يقوم أيضاً بتعيين تركيز المنطقية على العنصر.
يشتمل هذا الموضوع على الأقسام التالية.
- التركيز على لوحة المفاتيح
- تركيز منطقي
- التنقل باستخدام لوحة المفاتيح
- تنقل التركيز برمجياً
- أحداث التركيز
- موضوعات ذات صلة
التركيز على لوحة المفاتيح
يشير تركيز لوحة المفاتيح إلى العنصر الذي يتلقى حالياً إدخال من لوحة المفاتيح. يمكن أن يكون هناك عنصر واحد فقط على desktop لديه تركيز لوحة المفاتيح. في WPF ، يتم تعيين IsKeyboardFocused للعنصر الذي لديه تركيز لوحة المفاتيح إلى true. الخاصية الثابتة FocusedElement على فئة Keyboard تحصل على العنصر الذي لديه حالياً تركيز لوحة المفاتيح.
من أجل حصول العنصر على تركيز لوحة المفاتيح, يجب تعيين خصائص Focusable و IsVisible على العناصر الأساسية إلى true. بعض الفئات، مثل الفئة الأساسية Panel، يتم تعيين Focusable إلى false بشكل افتراضي; لذلك, يجب عليك تعيين Focusable إلى true إذا كنت تريد هذا العنصر أن يتمكن من الحصول على تركيز لوحة المفاتيح.
يمكن الحصول على تركيز لوحة المفاتيح خلال تفاعل المستخدم مع واجهة المستخدم, مثل جدولة العنصر أو النقر فوق الماوس على عناصر معينة. يمكن الحصول على تركيز لوحة المفاتيح أيضاً برمجياً باستخدام أسلوب Focus على فئة Keyboard. أسلوب Focus يحاول إعطاء العنصر المحدد تركيز لوحة المفاتيح. العنصر الذي تم إرجاعه هو العنصر الذي يحتوي على تركيز لوحة المفاتيح و هو ربما يكون مختلف عن العنصر المطلوب إذا حظر الكائن التركيز القديم أو الجديد الطلب.
يستخدم المثال التالي أسلوب Focus لتعيين تركيز لوحة المفاتيح على Button.
Private Sub OnLoaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
' Sets keyboard focus on the first Button in the sample.
Keyboard.Focus(firstButton)
End Sub
private void OnLoaded(object sender, RoutedEventArgs e)
{
// Sets keyboard focus on the first Button in the sample.
Keyboard.Focus(firstButton);
}
خاصية IsKeyboardFocused على فئات العنصر الأساسي تحصل على قيمة تشير إلى ما إذا كان العنصر لديه تركيز لوحة المفاتيح. خاصية IsKeyboardFocusWithin على فئات العنصر الأساسي تحصل على قيمة تشير إلى ما إذا كان العنصر أو أحد العناصر التابعة المرئية الخاصة به لديه تركيز لوحة المفاتيح.
عند تعيين التركيز الأولي عند إعداد التطبيق, العنصر المتلقي التركيز يجب أن يكون في الشجرة المرئية الخاصة بالنافذة الأولي التي تحميلها من قبل التطبيق, كما يجب تعيين Focusable و IsVisible إلى true. المكان المستحسن لتعيين التركيز الأولي هو في معالج الحدث Loaded. يمكن استخدام رد اتصال Dispatcher أيضاً عن طريق استدعاء Invoke أو BeginInvoke.
تركيز منطقي
التركيز المنطقي يشير إلى FocusManager.FocusedElement في نطاق التركيز. نطاف التركيز هو عبارة عن عنصر يحتفظ بمعلومات عن FocusedElement داخل نطاقه. عندما يترك تركيز لوحة المفاتيح نطاق تركيز، عنصر المركز سيفقد تركيز لوحة المفاتيح ولكن سيحتفظ بتركيز المنطقية. عندما يعود تركيز لوحة المفاتيح إلى نطاق التركيز، سيحصل العنصر المركز علي تركيز لوحة المفاتيح. يسمح هذا لتركيز لوحة المفاتيح أن يتغير بين عدة نطاقات التركيز ولكن يؤكد أن العنصر المركز في النطاق التركيز يستعيد تركيز لوحة المفاتيح عند رجوع التركيز إلى نطاق التركيز.
يمكن أن يكون هناك عدة عناصر لديها تركيز منطقي في التطبيق ولكن يوجد فقط عنصر واحد لديه تركيز منطقي في نطاق تركيز معين.
العنصر الذي لديه تركيز لوحة المفاتيح يكون لديه تركيز المنطقية في نطاق التركيز الذي ينتمي إليه.
يمكن تحويل العنصر إلى نطاق تركيز في Extensible Application Markup Language (XAML) بواسطة تعيين الخاصية المرفقة إلى FocusManager IsFocusScope إلى true. في التعليمات البرمجية، يمكن تحويل عنصر إلى نطاق تركيز عن طريق استدعاء SetIsFocusScope.
يجعل المثال التالي StackPanel نطاق تركيز بواسطة تعيين الخاصية المرفقة IsFocusScope.
<StackPanel Name="focusScope1"
FocusManager.IsFocusScope="True"
Height="200" Width="200">
<Button Name="button1" Height="50" Width="50"/>
<Button Name="button2" Height="50" Width="50"/>
</StackPanel>
Dim focuseScope2 As New StackPanel()
FocusManager.SetIsFocusScope(focuseScope2, True)
StackPanel focuseScope2 = new StackPanel();
FocusManager.SetIsFocusScope(focuseScope2, true);
يقوم GetFocusScope بإرجاع نطاق التركيز للعنصر المحدد.
الفئات في WPF التي هي نطاقات تركيز بشكل افتراضي Window ، MenuItem ، ToolBar ، و ContextMenu.
GetFocusedElementيحصل تركيز عنصر الفرعي تركيز نطاق. SetFocusedElementتعيين تركيز عنصر في المحدد تركيز نطاق. SetFocusedElementهو يستخدم عادة لتعيين الأولية العناصر التي تم التركيز عليها.
يقوم المثال التالي بتعيين العنصر المركز على نطاق التركيز و يحصل على العنصر المركز في نطاق التركيز.
' Sets the focused element in focusScope1
' focusScope1 is a StackPanel.
FocusManager.SetFocusedElement(focusScope1, button2)
' Gets the focused element for focusScope 1
Dim focusedElement As IInputElement = FocusManager.GetFocusedElement(focusScope1)
// Sets the focused element in focusScope1
// focusScope1 is a StackPanel.
FocusManager.SetFocusedElement(focusScope1, button2);
// Gets the focused element for focusScope 1
IInputElement focusedElement = FocusManager.GetFocusedElement(focusScope1);
التنقل باستخدام لوحة المفاتيح
فئة KeyboardNavigation هي المسؤولة عن تنفيذ تنقل تركيز لوحة المفاتيح الافتراضي عند الضغط على واحد من مفاتيح التنقل. مفاتيح التنقل هي: مفاتيح TAB و SHIFT + TAB, CTRL + TAB, CTRL + SHIFT + TAB, UPARROW ، DOWNARROW ، LEFTARROW و RIGHTARROW.
يمكن تغيير سلوك التنقل لحاوية التنقل بواسطة تعيين الخصائص المرفقة إلى KeyboardNavigation TabNavigation ، ControlTabNavigation ، و DirectionalNavigation. تكون هذه الخصائص من نوع KeyboardNavigationMode وتكون القيم الممكنة Continue ، Local ، Contained ، Cycle ، Once ، و None. القيمة الافتراضية هي Continue ، مما يعني أن العنصر ليس حاوية التنقل.
يقوم المثال التالي بإنشاء Menu مع عدد من كائنات MenuItem. يتم تعيين الخاصية المرفقة TabNavigation إلى Cycle على Menu. عند تغير التركيز باستخدام مفتاح التبويب ضمن Menu, سيتم نقل التركيز من كل عنصر و عند الوصول إلى العنصر الأخير سيتم إرجاع التركيز إلى العنصر الأول.
<Menu KeyboardNavigation.TabNavigation="Cycle">
<MenuItem Header="Menu Item 1" />
<MenuItem Header="Menu Item 2" />
<MenuItem Header="Menu Item 3" />
<MenuItem Header="Menu Item 4" />
</Menu>
Dim navigationMenu As New Menu()
Dim item1 As New MenuItem()
Dim item2 As New MenuItem()
Dim item3 As New MenuItem()
Dim item4 As New MenuItem()
navigationMenu.Items.Add(item1)
navigationMenu.Items.Add(item2)
navigationMenu.Items.Add(item3)
navigationMenu.Items.Add(item4)
KeyboardNavigation.SetTabNavigation(navigationMenu, KeyboardNavigationMode.Cycle)
Menu navigationMenu = new Menu();
MenuItem item1 = new MenuItem();
MenuItem item2 = new MenuItem();
MenuItem item3 = new MenuItem();
MenuItem item4 = new MenuItem();
navigationMenu.Items.Add(item1);
navigationMenu.Items.Add(item2);
navigationMenu.Items.Add(item3);
navigationMenu.Items.Add(item4);
KeyboardNavigation.SetTabNavigation(navigationMenu,
KeyboardNavigationMode.Cycle);
تنقل التركيز برمجياً
API إضافية للعمل مع التركيز هى MoveFocus و PredictFocus.
يقوم MoveFocus بتغير التركيز للعنصر التالي في التطبيق. يُستخدم TraversalRequest لتحديد الاتجاه. FocusNavigationDirectionالذى يتم تمريره الى MoveFocus يحدد الاتجاهات المختلفة حيث يمكن نقل التركيز, مثل First ، Last ، Up و Down.
يستخدم المثال التالي MoveFocus لتغيير العنصر المركز.
' Creating a FocusNavigationDirection object and setting it to a
' local field that contains the direction selected.
Dim focusDirection As FocusNavigationDirection = _focusMoveValue
' MoveFocus takes a TraveralReqest as its argument.
Dim request As New TraversalRequest(focusDirection)
' Gets the element with keyboard focus.
Dim elementWithFocus As UIElement = TryCast(Keyboard.FocusedElement, UIElement)
' Change keyboard focus.
If elementWithFocus IsNot Nothing Then
elementWithFocus.MoveFocus(request)
End If
// Creating a FocusNavigationDirection object and setting it to a
// local field that contains the direction selected.
FocusNavigationDirection focusDirection = _focusMoveValue;
// MoveFocus takes a TraveralReqest as its argument.
TraversalRequest request = new TraversalRequest(focusDirection);
// Gets the element with keyboard focus.
UIElement elementWithFocus = Keyboard.FocusedElement as UIElement;
// Change keyboard focus.
if (elementWithFocus != null)
{
elementWithFocus.MoveFocus(request);
}
يقوم PredictFocus بإرجاع الكائن الذي قد يتلقى التركيز إذا تم تغيير التركيز. حالياً، فقط Up ، Down ، Left ، و Right هم معتمدين من قبل PredictFocus.
أحداث التركيز
الأحداث المتعلقة بتركيز لوحة المفاتيح هم PreviewGotKeyboardFocus ، GotKeyboardFocus و PreviewLostKeyboardFocus ، LostKeyboardFocus. يتم تعريف الأحداث كـأحداث مرفقة على فئة Keyboard ولكن يمكن الوصول إليها بشكل أكثر سهولة كأحداث موجهة مكافئة على فئات عنصر الأساس. لمزيد من المعلومات حول الأحداث، راجع نظرة عامة حول الأحداث الموجهة.
GotKeyboardFocusهو مرفوع عندما يحصل على العنصر تركيز لوحة المفاتيح. LostKeyboardFocusعندما يفقد العنصر تركيز لوحة المفاتيح. إذا تم معالجة حدث PreviewGotKeyboardFocus أو حدث PreviewLostKeyboardFocusEvent و تم تعيين Handled إلى true ، التركيز لا يتغيير.
المثال التالي يرفق معالجات الأحداث GotKeyboardFocus و LostKeyboardFocus إلى TextBox.
<Border BorderBrush="Black" BorderThickness="1"
Width="200" Height="100" Margin="5">
<StackPanel>
<Label HorizontalAlignment="Center" Content="Type Text In This TextBox" />
<TextBox Width="175"
Height="50"
Margin="5"
TextWrapping="Wrap"
HorizontalAlignment="Center"
VerticalScrollBarVisibility="Auto"
GotKeyboardFocus="TextBoxGotKeyboardFocus"
LostKeyboardFocus="TextBoxLostKeyboardFocus"
KeyDown="SourceTextKeyDown"/>
</StackPanel>
</Border>
عند يحصل TextBox على تركيز لوحة المفاتيح, يتم تغيير خاصية Background التابعة إلى TextBox إلى LightBlue.
Private Sub TextBoxGotKeyboardFocus(ByVal sender As Object, ByVal e As KeyboardFocusChangedEventArgs)
Dim source As TextBox = TryCast(e.Source, TextBox)
If source IsNot Nothing Then
' Change the TextBox color when it obtains focus.
source.Background = Brushes.LightBlue
' Clear the TextBox.
source.Clear()
End If
End Sub
private void TextBoxGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
TextBox source = e.Source as TextBox;
if (source != null)
{
// Change the TextBox color when it obtains focus.
source.Background = Brushes.LightBlue;
// Clear the TextBox.
source.Clear();
}
}
عند يفقد TextBox تركيز لوحة المفاتيح, يتم تغيير خاصية Background التابعة إلى TextBox مرة أخرى إلى الأبيض.
Private Sub TextBoxLostKeyboardFocus(ByVal sender As Object, ByVal e As KeyboardFocusChangedEventArgs)
Dim source As TextBox = TryCast(e.Source, TextBox)
If source IsNot Nothing Then
' Change the TextBox color when it loses focus.
source.Background = Brushes.White
' Set the hit counter back to zero and updates the display.
Me.ResetCounter()
End If
End Sub
private void TextBoxLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
TextBox source = e.Source as TextBox;
if (source != null)
{
// Change the TextBox color when it loses focus.
source.Background = Brushes.White;
// Set the hit counter back to zero and updates the display.
this.ResetCounter();
}
}
الأحداث المتعلقة بتركيز المنطقية هم GotFocus ، LostFocus و ، . يتم تعريف هذه الأحداث تشغيل FocusManagerكأحداث المرفق، ولكن FocusManagerلا يعرض wrappers حدث CLR. UIElementوContentElementكشف هذه الأحداث بطريقة أكثر ملائمة.