2009-05-19 3 views
3

그래서 사용자 지정 데이터 템플릿이있는 ComboBox가 있다고 가정 해 보겠습니다.단추가 포함 된 ItemTemplate이있는 ComboBox

<ComboBox Width="150" ItemsSource="{Binding MyItems}"> 
    <ComboBox.ItemTemplate> 
     <DataTemplate> 
      <Button Content="ClickMe" /> 
     </DataTemplate> 
    </ComboBox.ItemTemplate> 
</ComboBox> 

이 가진 문제는 버튼 클릭을 먹는 것을, 그리고 버튼을 선택하면 항목이 선택되지 않습니다 : 데이터 템플릿에있는 항목 중 하나는 버튼입니다. 이는 풀다운이 사라지지 않고 항목이 선택되지 않음을 의미합니다.

왜 이런 일이 발생합니까?

해결 방법이 있습니까? 단추 클릭 (나는 명령에 바인딩)을 처리하고 콤보 상자가 클릭을 처리 할 수 ​​있도록 체인을 계속 진행할 가능성이 있습니까?

참고 : Silverlight에서 내 문제가 나타나지만 WPF에서 똑같은 문제가 발생할 수 있습니다.

답변

1

가장 좋은 방법은 버튼의 명령에서 SelectedItem을 설정하는 것입니다.

+0

그래, 생각해 봤지만 콤보 상자가 만드는 풀다운을 무시하지 않습니다. –

+0

ComboBox에는 IsOpen (또는 비슷한 항목) 속성이 있습니다.이 속성을 False로 설정할 수 있습니다. Focusable = "False"를 단추에 설정하여 자동으로 실행되도록 할 수도 있습니다. –

+0

그래, 둘의 조합이 끝났다. 전체 솔루션에 대한 내 대답을 참조하십시오,하지만 당신에게 신용 포인트를주고 싶습니다, 그래서 나는 당신의 대답을 올바른 것으로 표시하고 있습니다. –

0

내가 원하는 것을 할 수있는 방법이 있는지 나는 모른다. 예를 들어 ButtonListBox에 넣으 려한다면 동일한 동작이 발생합니다. Button을 클릭해도 ListBox의 항목이 선택되지 않습니다. 사실, 이것은 선택을 지원하는 ItemsControl의 모든 컨트롤의 경우입니다.

Click 이벤트로 뭔가를 할 수 있고 처리되지 않은 것으로 표시하여 시각적 트리까지 계속 진행할 수 있지만 작동 여부를 알 수는 없습니다.

8

좋아, 알아 냈어. 그것은 총 해킹,하지만 여전히 나를 버튼 내 명령을 결합하고 항목을 선택하는 콤보 박스 동작을 계속 할 수 있습니다 :

<ComboBox x:Name="MyCombo" Width="150" ItemsSource="{Binding MyItems}"> 
    <ComboBox.ItemTemplate> 
     <DataTemplate> 
      <Button Content="ClickMe" Click="Button_Click" /> 
     </DataTemplate> 
    </ComboBox.ItemTemplate> 
</ComboBox> 

을 그리고 뒤에 코드 :

private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    MyCombo.SelectedItem = (sender as Button).DataContext; 
    MyCombo.IsDropDownOpen = false; 
} 

정말로 원한다면 SelectedItem 및 IsDropDownOpen을 ViewModel의 속성에 바인딩 할 수 있지만이 동작을 XAML의 해킹 확장으로 유지하기로 결정하여 내 ViewModel을 깨끗하게 유지하려고했습니다.

1

MVVM 컨텍스트에 대한 또 다른 가능성을 발견했습니다. ComboBox에 대해 파생 클래스를 사용했으며 항목이 ButtonBase에서 파생 된 adden 인 경우 이벤트에 연결하여 ComboBox을 닫습니다.

이것은 내 프로젝트에서 작동하지만 버튼 자체가 버튼이기 때문에 버튼 만 자식 요소로 포함하면 작동하지 않습니다.

public class MyComboBox : ComboBox 
{ 
    public MyComboBox() 
    { 
     // use Loaded event to modify inital items. 
     Loaded += OnLoaded; 
    } 

    private void OnLoaded(object sender, RoutedEventArgs routedEventArgs) 
    { 
     if (Items != null) 
     { 
      foreach (var item in Items) 
      { 
       var button = item as ButtonBase; 
       if (button != null) 
       { 
        ModifyButtonItem(button); 
       } 
      } 
     } 
    } 

    protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
    { 
     base.OnItemsChanged(e); 
     // Check added items. If an item is a button, modify the button. 
     if (e.NewItems != null) 
     { 
      foreach (var item in e.NewItems) 
      { 
       var button = item as ButtonBase; 
       if (button != null) 
       { 
        ModifyButtonItem(button); 
       } 
      } 
     } 
    } 

    private void ModifyButtonItem(ButtonBase button) 
    { 
     button.Click += (sender, args) => { IsDropDownOpen = false; }; 
    } 
}