2009-06-12 19 views
6

इस उदाहरण विंडो में, टैबबिंग पहले टेक्स्टबॉक्स से, अंतिम टेक्स्टबॉक्स में और फिर विस्तारक शीर्षलेख पर जाता है।मैं एक WPF विस्तारक नियंत्रण पर TabIndex कैसे सेट कर सकता हूं?

<Window x:Class="ExpanderTab.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="300" Width="300" 
    FocusManager.FocusedElement="{Binding ElementName=FirstField}"> 
    <StackPanel> 
     <TextBox TabIndex="10" Name="FirstField"></TextBox> 
     <Expander TabIndex="20" Header="_abc"> 
      <TextBox TabIndex="30"></TextBox> 
     </Expander> 
     <TextBox TabIndex="40"></TextBox> 
    </StackPanel> 
</Window> 

जाहिर है, मैं इसे पहले टेक्स्ट बॉक्स, विस्तारक शीर्षलेख, फिर अंतिम टेक्स्टबॉक्स पर जाना चाहता हूं। क्या विस्तारक के शीर्षलेख में TabIndex असाइन करने का कोई आसान तरीका है?

मैं विस्तारक मजबूर कर एक tabstop KeyboardNavigation.IsTabStop="True" उपयोग करने के लिए कोशिश की है, लेकिन वह सारा ध्यान विस्तारक प्राप्त करता है, और पूरे विस्तारक स्पेस बार करने के लिए प्रतिक्रिया नहीं करता। दो और टैब के बाद, हेडर फिर से चुना जाता है और मैं इसे स्पेसबार के साथ खोल सकता हूं।

संपादित करें: मैं ऐसे किसी भी व्यक्ति के लिए एक बक्षीस फेंक दूंगा जो ऐसा करने के लिए क्लीनर तरीके से आ सकता है - यदि नहीं, तो rmoore, आप प्रतिनिधि हो सकते हैं। आपकी सहायता के लिए धन्यवाद.

+0

मैं सब कुछ आप चाहते हैं – jjxtra

उत्तर

10

निम्नलिखित कोड होगा TabIndex गुणों के बिना भी काम करते हैं, वे अपेक्षित टैब ऑर्डर के बारे में स्पष्टता के लिए शामिल होते हैं।

<Window x:Class="ExpanderTab.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300" FocusManager.FocusedElement="{Binding ElementName=FirstField}"> 
    <StackPanel> 
     <TextBox TabIndex="10" Name="FirstField"></TextBox> 
     <Expander TabIndex="20" Header="Section1" KeyboardNavigation.TabNavigation="Local"> 
      <StackPanel KeyboardNavigation.TabNavigation="Local"> 
       <TextBox TabIndex="30"></TextBox> 
       <TextBox TabIndex="40"></TextBox> 
      </StackPanel> 
     </Expander> 
     <Expander TabIndex="50" Header="Section2" KeyboardNavigation.TabNavigation="Local"> 
      <StackPanel KeyboardNavigation.TabNavigation="Local"> 
       <TextBox TabIndex="60"></TextBox> 
       <TextBox TabIndex="70"></TextBox> 
      </StackPanel> 
     </Expander> 
     <TextBox TabIndex="80"></TextBox> 
    </StackPanel> 
</Window> 
+0

बहुत अच्छा, क्या विस्तारित होने पर टैबइंडेक्स का सम्मान करने का कोई तरीका है? – rmoore

+0

मैं इसे देख लूंगा और इस जवाब को अपडेट कर दूंगा जब मेरे पास – jjxtra

+0

बहुत अच्छा है! – Eclipse

3

मुझे एक रास्ता मिला, लेकिन कुछ बेहतर होना है।


मोल के माध्यम से एक्सपेंडर को देखकर, या ब्लेंड द्वारा उत्पन्न कंट्रोल टेम्पलेट को देखकर हम देख सकते हैं कि हेडर भाग जो स्पेस/एंटर/क्लिक/इत्यादि का जवाब दे रहा है वास्तव में एक टॉगल बटन है। अब बुरी खबर, क्योंकि हेडर टॉगल बटन के पास एक्सपेंडर के विस्तारित गुणों के लिए एक अलग लेआउट है, ऊपर/नीचे/बाएं/दाएं इसे पहले से ही विस्तारक के नियंत्रण टेम्पलेट के माध्यम से सौंपा गया शैलियों है। इससे हमें एक्सपेंडर के संसाधनों में डिफ़ॉल्ट टॉगल बटन शैली बनाने जैसी कुछ सरल करने से रोक दिया जाता है।

alt text http://i44.tinypic.com/2dlq1pl.png

तुम्हारे पीछे कोड की पहुंच है, या संसाधन शब्दकोश के लिए एक codebehind कहा कि विस्तारक में है कोई आपत्ति नहीं है, तो आप ToggleButton पहुँच सकते हैं और Expander में tabindex सेट कर सकते हैं। लोडेड घटना, इस तरह:

<Expander x:Name="uiExpander" 
      Header="_abc" 
      Loaded="uiExpander_Loaded" 
      TabIndex="20" 
      IsTabStop="False"> 
    <TextBox TabIndex="30"> 

    </TextBox> 
</Expander> 


private void uiExpander_Loaded(object sender, RoutedEventArgs e) 
{ 
    //Gets the HeaderSite part of the default ControlTemplate for an Expander. 
    var header = uiExpander.Template.FindName("HeaderSite", uiExpander) as Control; 
    if (header != null) 
    { 
     header.TabIndex = uiExpander.TabIndex; 
    } 
} 

तुम भी सिर्फ एक ऍक्स्प करने के लिए इस वस्तु डाल सकता एंडर भी, अगर आपको इसे कई विस्तारकों के साथ काम करने की ज़रूरत है। दूसरा विकल्प, विस्तारक के लिए अपना स्वयं का कंट्रोल टेम्पलेट बनाना है और इसे वहां सेट अप करना है।

संपादित हम यह भी एक AttachedProperty करने के लिए कोड भाग ले जा सकते हैं, यह अधिक स्वच्छ और आसान उपयोग करने के लिए कर रही है:

<Expander local:ExpanderHelper.HeaderTabIndex="20"> 
    ... 
</Expander> 

और AttachedProperty:

public class ExpanderHelper 
{ 
    public static int GetHeaderTabIndex(DependencyObject obj) 
    { 
     return (int)obj.GetValue(HeaderTabIndexProperty); 
    } 

    public static void SetHeaderTabIndex(DependencyObject obj, int value) 
    { 
     obj.SetValue(HeaderTabIndexProperty, value); 
    } 

    // Using a DependencyProperty as the backing store for HeaderTabIndex. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty HeaderTabIndexProperty = 
     DependencyProperty.RegisterAttached(
     "HeaderTabIndex", 
     typeof(int), 
     typeof(ExpanderHelper), 
     new FrameworkPropertyMetadata(
      int.MaxValue, 
      FrameworkPropertyMetadataOptions.None, 
      new PropertyChangedCallback(OnHeaderTabIndexChanged))); 

    private static void OnHeaderTabIndexChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) 
    { 
     var expander = o as Expander; 
     int index; 

     if (expander != null && int.TryParse(e.NewValue.ToString(), out index)) 
     { 
      if (expander.IsLoaded) 
      { 
       SetTabIndex(expander, (int)e.NewValue); 
      } 
      else 
      { 
       // If the Expander is not yet loaded, then the Header will not be costructed 
       // To avoid getting a null refrence to the HeaderSite control part we 
       // can delay the setting of the HeaderTabIndex untill after the Expander is loaded. 
       expander.Loaded += new RoutedEventHandler((i, j) => SetTabIndex(expander, (int)e.NewValue)); 
      } 
     } 
     else 
     { 
      throw new InvalidCastException(); 
     } 
    } 

    private static void SetTabIndex(Expander expander, int index) 
    { 
     //Gets the HeaderSite part of the default ControlTemplate for an Expander. 
     var header = expander.Template.FindName("HeaderSite", expander) as Control; 
     if (header != null) 
     { 
      header.TabIndex = index; 
     } 
    } 
} 
+0

हाँ, मैं अपने खुद के ControlTemplate के साथ प्रयोग करना किया गया है करने के लिए मेरा उत्तर अद्यतन, लेकिन यह एक निरपेक्ष जानवर है। जैसा कि आपने कहा, एक बेहतर तरीका होना चाहिए। – Eclipse

संबंधित मुद्दे