2010-01-27 2 views
3

WPF ComboBoxIsEditable 속성을 켜고 끌 수있는 뷰 모델에 바인딩 된 속성이 있습니다. 스위치를 켜면 ComboBox에 포커스를두고 편집 ​​TextBox의 모든 텍스트를 선택하고 싶습니다.WPF : 모든 텍스트 선택 및 ComboBox의 편집 가능한 텍스트 상자에 포커스 설정

이 작업을 수행하는 데 가장 좋은 방법이 없습니다. ControlTemplate을 대체해야하고 기본 클래스 ComboBox을 서브 클래스 화하고 필요한 속성을 제공하고, 첨부 된 속성 또는 다른 방법을 사용합니까?

답변

6

해결책이 있습니다.

모델 -view-ViewModel 및 첨부 속성 접근 방식을 사용하고 있습니다.

첫째, 당신은이 작업을 할 수 MVVM에서 메시징 시스템을 알아야 할뿐만 아니라 명령을 알고있다. Attached Properties로 시작하여 IsFocused 이벤트를 집중시키기를 원하는 콤보 상자와 모든 텍스트를 선택하기 시작합니다. 이 코드와 무엇

#region Select On Focus 

    public static bool GetSelectWhenFocused(DependencyObject obj) 
    { 
    return (bool)obj.GetValue(SelectWhenFocusedProperty); 
    } 

    public static void SetSelectWhenFocused(DependencyObject obj, bool value) 
    { 
    obj.SetValue(SelectWhenFocusedProperty, value); 
    } 

    // Using a DependencyProperty as the backing store for SelectWhenFocused. This enables animation, styling, binding, etc... 
    public static read-only DependencyProperty SelectWhenFocusedProperty = 
     DependencyProperty.RegisterAttached("SelectWhenFocused", typeof(bool), typeof(EditableComboBox), new UIPropertyMetadata(OnSelectOnFocusedChanged)); 

    public static void OnSelectOnFocusedChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) 
    { 
    bool SetProperty = (bool)args.NewValue;  

    var comboBox = obj as ComboBox; 
    if (comboBox == null) return; 

    if (SetProperty) 
    { 
     comboBox.GotFocus += GotFocused; 
     Messenger.Default.Register<ComboBox>(comboBox, Focus); 
    } 
    else 
    { 
     comboBox.GotFocus -= GotFocused; 
     Messenger.Default.Unregister<ComboBox>(comboBox, Focus); 
    } 
    } 

    public static void GotFocused(object sender, RoutedEventArgs e) 
    { 
    var comboBox = sender as ComboBox; 
    if(comboBox == null) return; 

    var textBox = comboBox.FindChild(typeof(TextBox), "PART_EditableTextBox") as TextBox; 
    if (textBox == null) return; 

    textBox.SelectAll(); 
    } 

    public static void Focus(ComboBox comboBox) 
    { 
    if(comboBox == null) return; 
    comboBox.Focus(); 
    } 
    #endregion 

우리가 연결된 속성 사실에 SelectWhenFocused 설정하면, 그것은 GotFocused 이벤트를 수신하고 내부의 모든 텍스트를 선택 등록 할 것이다. 사용하려면

은 간단하다 :

<ComboBox 
    IsEditable="True" 
    ComboBoxHelper:EditableComboBox.SelectWhenFocused="True" 
    x:Name="EditBox" /> 

이제 우리는 클릭 할 때 콤보 상자에 포커스를 설정하는 버튼이 필요합니다. CommandParameter 그 이름 편집 상자에 의해 콤보 상자에 바인딩하는 방법을

<Button 
    Command="{Binding Focus}" 
    CommandParameter="{Binding ElementName=EditBox}" 
    Grid.Column="1" >Focus</Button> 

알 수 있습니다. 명령을 실행하면이 ComboBox 만 포커스되고 모든 텍스트가 선택됩니다.

public SimpleCommand Focus { get; set; } 
public WindowVM() 
{ 
    Focus = new SimpleCommand {ExecuteDelegate = x => Broadcast(x as ComboBox)}; 
} 

이 나를 위해 작동 테스트 및 검증 된 기술이다 : 내 뷰 모델에서

, 나는 다음과 같은 선언 초점 명령 있습니다. 나는 그것이 당신의 문제에 대한 잔인한 해결책이 아니기를 바랍니다. 행운을 빕니다.

+0

감사합니다. Tri. 이 패턴을 구현했지만 ComboBox에 FindChild 메소드가 없다는 것을 알 수 있습니다. – codekaizen

+0

죄송합니다, FindChild 여기에 있습니다 : http://stackoverflow.com/questions/636383/wpf-ways-to-find-controls/1501391#1501391 –

+0

Thanks, Tri. 내가 약간 궁금해지면 구현을 추측했다. 내가 가깝게 생긴 것 같아. 그러나 TextBox 자식을 찾을 수 없으며 ComboBox의 IsEditable 속성을 변경하는 복잡한 요소가있을 가능성이 높습니다. 그리고 GotFocused 이벤트가 처리 될 때 ComboBox 컨트롤 템플릿이 아직 변경되지 않았으며 TextBox가 만들어지지 않습니다. 제어 템플릿이 적용될 때까지 검색을 연기하는 방법에 대한 통찰력? – codekaizen

관련 문제