2012-01-05 11 views
7

Breve storia: un ListBox all'interno di un ambito di messa a fuoco non consente di selezionare un elemento.Utilizzare ListBox in Focus Scope

Lunga storia:

Sto cercando di fare un widget sensibile al contesto per l'immissione dei dati. Ho il pannello principale con diversi campi. Di seguito, ho un pannello con FocusManager.FocusScope="True". Questo pannello verrà riempito con il widget pertinente per il campo che al momento è focalizzato. Ad esempio, selezionando un campo data verrà mostrato un calendario nella parte inferiore dello schermo.

Ho diversi controlli che richiedono all'utente di selezionare uno dei molti valori da un elenco. Metto un ListBox nella gamma di messa a fuoco, ma non riesco a selezionare alcun elemento. Quando qualcosa è selezionato (programmaticamente) e fai clic su ListBox, deseleziona tutto.

Ho verificato alcuni eventi e non sta rilevando eventi MouseDown, ma sta rilevando eventi MouseMove. Spara GotFocus ogni volta che clicco su un oggetto, ma non spara mai a LostFocus. Non sono sicuro di cosa significhi, ma spero che possa essere d'aiuto a qualcuno che sta leggendo questo.

Ecco il codice che sto usando per visualizzare il widget sensibile al contesto. Ho il seguente codice XAML nella mia finestra:

<Grid x:Name="EntryWidget" FocusManager.IsFocusScope="True"> 
    <Grid.Resources> 
     <ListBox x:Key="List" ItemsSource="{Binding}" /> 
    </Grid.Resources> 
</Grid> 

uso il Window.GotFocus evento indirizzato ad aggiornare il widget per il controllo appropriato, in questo modo:

private void Window_GotFocus(object sender, RoutedEventArgs e) 
{ 
    FrameworkElement focus = (FrameworkElement)FocusManager.GetFocusedElement(this); 
    EntryWidget.Children.Clear(); // Could this be the culprit? 
    object tag = focus.Tag; 
    if (tag != null) 
    { 
     if (EntryWidget.Resources.Contains(tag)) 
     { 
      EntryWidget.Children.Add(EntryWidget.Resources[tag] as UIElement); 
     } 
    } 
} 

Quindi:

  1. C'è un modo per far funzionare il ListBox in un ambito di messa a fuoco?

  2. Oppure esiste un altro controllo di elenco che funzioni meglio all'interno di un ambito di messa a fuoco?

  3. O sto prendendo l'approccio sbagliato utilizzando gli ambiti di messa a fuoco? I miei requisiti: l'utente deve essere in grado di selezionare una voce da un elenco a scorrimento, che entrerà il valore nel campo corrente. Il campo corrente non dovrebbe perdere la concentrazione.

+0

Non sono abbastanza sicuro di ciò che si sta tentando di fare, ma si è guardato al collegamento delle viste di raccolta, questo è quando un elemento di una raccolta viene selezionato mentre l'altra raccolta viene aggiornata automaticamente. Ecco un collegamento da MSDN http://msdn.microsoft.com/en-us/library/system.windows.data.collectionview.aspx – mihajlv

+0

Ho solo un ListBox. Quando un elemento è selezionato, dovrebbe aggiornare il TextBox che ha lo stato attivo. Ma non posso selezionare alcun oggetto. –

+0

come su questo, se si dispone di un dp di tipo textbox che viene aggiornato da una casella di testo quando diventa attivo, impostando il dp uguale a se stesso. Quindi quando fai clic su un elenco, aggiorni il dp che ha la casella di testo dell'ultimo elemento che ha il focus, so che è una soluzione, ma dovrebbe funzionare. – mihajlv

risposta

1

Quando si fa clic sul ListBox o su un elemento in esso contenuto, si imposta lo stato attivo della tastiera per l'oggetto ListBox. Ciò accade indipendentemente dagli ambiti di messa a fuoco che hai definito.

È possibile definire un ambito attenzione per la tomaia pannello (quello contenente i campi), e hanno SelectionChanged set attenzione del ListBox al pannello superiore, che effettivamente impostato attivo alla voce che è stata concentrata in quel pannello prima di fare clic su qualsiasi elemento ListBox.

<StackPanel> 
    <StackPanel x:Name="upperPanel" FocusManager.IsFocusScope="True" GotFocus="upperPanel_GotFocus"> 
     <TextBox x:Name="TextBox1"></TextBox> 
     <TextBox x:Name="TextBox2"></TextBox> 
    </StackPanel> 
    <StackPanel> 
     <ListBox x:Name="ListBox1" SelectionChanged="ListBox_SelectionChanged"> 
      <ListBoxItem>First</ListBoxItem> 
      <ListBoxItem>Second</ListBoxItem> 
      <ListBoxItem>Third</ListBoxItem> 
     </ListBox> 

     <ListBox x:Name="ListBox2" SelectionChanged="ListBox_SelectionChanged"> 
      <ListBoxItem>4</ListBoxItem> 
      <ListBoxItem>5</ListBoxItem> 
      <ListBoxItem>6</ListBoxItem> 
     </ListBox> 
    </StackPanel> 
</StackPanel> 

private IInputElement focusedElement = null; 

private void upperPanel_GotFocus(object sender, RoutedEventArgs e) 
{ 
    focusedElement = e.Source as IInputElement; 
} 

private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) 
{ 
    UpdateTextBoxValue((e.AddedItems[0] as ListBoxItem).Content.ToString()); 
} 

private void UpdateTextBoxValue(string text) 
{ 
    TextBox focusedTextBox = focusedElement as TextBox; 
    if (focusedTextBox != null) 
    { 
     focusedTextBox.Text = text; 
    } 

    upperPanel.Focus(); 
} 

Il controllo attualmente attivo nell'ambito upperPanel è mantenuta aggiornata dal gestore GotFocus eventi, e il metodo UpdateTextBoxValue è responsabile della creazione del testo sul controllo attivo TextBox e modificando lo stato attivo esso.

sto assumendo si ha familiarità con i termini stavo usando (focus della tastiera/attivo logico); in caso contrario, si può dare un'occhiata a Focus Overview o si può semplicemente chiedere.

+0

Hmm, sembra hackish. Ho diversi controlli oltre al ListBox che possono essere visualizzati per altri campi. Se devo fare che GetFocusedElement per ogni controllo che voglio visualizzare, uh, c'è un modo migliore? Hai detto che sta impostando lo stato attivo della tastiera su ListBox. In tal caso, perché si preme un tipo di chiave nel campo nel campo di messa a fuoco principale? Il ListBox non sembra avere il focus della tastiera. –

+0

@kendfrey Ho modificato la mia risposta. Se ti riferisci al mio esempio, premendo un tasto digita il testo nella casella di testo perché sto impostando lo stato attivo della tastiera su di esso dal codice. –

+0

Il campo 'focusedElement' non ha lo scopo di un ambito di messa a fuoco? E non mi riferisco al tuo codice. Il mio codice non mi consente (tastiera) di concentrarsi sul ListBox. Pubblicherò il codice che penso possa essere rilevante. –

2

La mia risposta sarebbe non utilizzare lo scopo di messa a fuoco per questo.

Stai quasi perdendo lo scopo della messa a fuoco. Cosa succede se qualcuno non può usare il mouse e vuole invece usare la tastiera?

perché non avere solo la selezione nell'elenco quindi impostare il focus sul controllo originale, invece di fare tutto questo lavoro extra con gli ambiti di messa a fuoco?

+0

Buon pensiero. Questa applicazione è progettata per un tablet PC, pertanto il supporto della tastiera non è una priorità elevata. Ma gli ambiti di messa a fuoco non sono progettati per una situazione come questa? Non sarebbe molto lavoro implementare il tuo sistema di messa a fuoco? –

+0

ma se è per un sistema tablet, solo con il tocco, a cosa serve la messa a fuoco? Se non lo stai usando per * keyboard focus *, allora non sono sicuro di cosa stai usando. –

+0

Potremmo lasciare che l'utente digiti direttamente. Se non usassi la messa a fuoco per tenere traccia del campo corrente, cosa dovrei usare allora? I suggerimenti di messa a fuoco, come un TextBox evidenziato, sono utili e sarebbe contro-intuitivo avere l'attenzione su altri controlli rispetto al campo corrente. E per favore non giudicarmi per aver tentato di inserire dati su un tablet. :) :( –