2008-11-30 26 views
9

TextBox içeren DataTemplate var. Bu şablonu bir seçimdeki bir liste kutusu öğesine ayarlıyorum.DataTemplate'de bir TextBox'ta odaklama

Şablonda metin kutusuna odağı ayarlayamıyorum. MyTemplate.FindName aramayı denedim, ancak geçersiz bir işlem özel durum ile biter: Bu işlem yalnızca bu şablonu uygulanmış olan öğeler için geçerlidir.

Buna nasıl erişebilirim?

cevap

9

Odaklanmak istediğiniz TextBox adını bildiğinizden, bu nispeten kolaydır. Buradaki fikir, şablonun ListBoxItem kendisine uygulandığı şekilde ele geçirilmesidir.

seçilen öğeyi almak yapmak istediğim

ilk şey:

public void FocusItem(ListBoxItem item, string name) 
{ 
    if (!item.IsLoaded) 
    { 
     // wait for the item to load so we can find the control to focus 
     RoutedEventHandler onload = null; 
     onload = delegate 
     { 
      item.Loaded -= onload; 
      FocusItem(item, name); 
     }; 
     item.Loaded += onload; 
     return; 
    } 

    try 
    { 
     var myTemplate = FindResource("MyTemplateKey") as FrameworkTemplate; // or however you get your template right now 

     var ctl = myTemplate.FindName(name, item) as FrameworkElement; 
     ctl.Focus(); 
    } 
    catch 
    { 
     // focus something else if the template/item wasn't found? 
    } 
} 

I:

var item = listBox1.ItemContainerGenerator.ContainerFromItem(listBox1.SelectedItem) as ListBoxItem; 

Sonra adına bağlı bir denetimi odaklanan bu küçük yardımcı fonksiyonu içine geçebilir zor olan bit öğenin yüklenmesini beklediğinizden emin olun. Bu kodu ekledim çünkü bu terimi ItemContainerGenerator.StatusChanged olayından çağırıyordum ve bazen ListBoxItem yöntemine girdiğimizde tam olarak başlatılmamıştı.

+1

FindResource bir nesne döndürür, bu yüzden bunu bir FrameworkTemplate'e uyguladığınızdan emin olun. – Michael

10

Bu eski olduğunu biliyorum, ama bugün bu konuda koştu ve sonunda bu kararı ile geldi: Bir öğe seçildiğinde TextBox yana

sadece yükleniyor ve bu istediğiniz zaman olduğu Ayarlanacak odak, TextBox.Load olayını işleyebilir ve Focus() numaralı telefonu arayabilirsiniz.

Bunu başarmanın iki yolu vardır.

1.

bir AutoFocusTextBox ile DataTemplate yılında TextBox değiştirin.

public class AutoFocusTextBox : TextBox 
{ 
    public AutoFocusTextBox() 
    { 
     Loaded += delegate { Focus(); }; 
    } 
} 

Eğer AutoFocusTextBox sizin .xaml dosyasında tanımlandığı ad başvurmak gerekir unutmayın.

2. DataTemplate'un tanımlandığı dosyanın codebehind dosyasına bir işleyici ekleyin.

SomeResourceDictionary.xaml

<TextBox Text="{Binding Something, Mode=TwoWay}" Style={StaticResource ... 
     Loaded="FocusTextBoxOnLoad" /> 

SomeResourceDictionary.xaml.cs Her iki seçenekte de

private void FocusTextBoxOnLoad(object sender, RoutedEventArgs e) 
    { 
     var textbox = sender as TextBox; 
     if(textbox == null) return; 
     textbox.Focus(); 
    } 

, her zaman böyle tüm metin seçmek gibi, işleyici diğer davranışları ekleyebilir .

2

Jay'in 2 öneri temiz - ve daha herhangi bir kontrol kolayca varsayılan yapılabilir böylece UIElement yerine TextBox kullanılarak genelleştirilmiş edilebilir: Tamam

private void FocusControlOnLoad(object sender, RoutedEventArgs e) 
{ 
    var uiElement = sender as UiElement; 
    if(uiElement == null) return; 
    uiElement.Focus(); 
} 
7

. Bu yüzden en iyi çözüme sahip olduğumu düşünüyorum. Yine de benim için çalıştı. Metin kutusuna odaklanmak istediğim basit bir veri şablonum var. FocusManager, odağı metin kutusuna teslim eder.

<DataTemplate x:Key="MyDataTemplate" DataType="ListBoxItem"> 
    <Grid> 
     <WrapPanel Orientation="Horizontal" FocusManager.FocusedElement="{Binding ElementName=tbText}"> 
      <CheckBox IsChecked="{Binding Path=Completed}" Margin="5" /> 
      <Button Style="{StaticResource ResourceKey=DeleteButtonTemplate}" Margin="5" Click="btnDeleteItem_Click" /> 
      <TextBox Name="tbText" 
        Text="{Binding Path=Text}" 
        Width="200" 
        TextWrapping="Wrap" 
        AcceptsReturn="True" 
        Margin="5" 
        Focusable="True"/> 
      <DatePicker Text="{Binding Path=Date}" Margin="5"/> 
     </WrapPanel> 
    </Grid> 
</DataTemplate> 
+0

Güzel ve temiz, benim için de çalışıyor ve beğendim – veljkoz

İlgili konular