2010-03-30 2 views
9

목록 상자의 MultiSelect 모드를 사용하여 this answer과 비슷한 ListBox의 ItemTemplate으로 사용되는 ToggleButtons 목록이 있습니다. 그러나 적어도 하나의 항목이 항상 선택되어 있는지 확인해야합니다.ToggleButton이 IsEnabled를 설정하지 않고 Toggled되는 것을 방지하려면 어떻게해야합니까?

ListBox의 SelectedItems 컬렉션에 ListBox.SelectionChanged 이벤트의 항목을 다시 추가하는 것으로 ListBox에서 적절한 동작을 얻을 수 있지만 이전 ToggleButton은 토글 된 상태에서 벗어나기 때문에 이전에 중지해야한다고 생각합니다. 과정.

마지막 버튼에 IsEnabled = "False"를 설정하지 않고이 버튼을 사용하고 싶습니다. 버튼 템플릿을 다시 실행하지 않고도 활성화 된 비주얼 스타일을 유지하려고합니다. 어떤 아이디어?

답변

28

당신은 기본 구현 호출하지 않음으로써, 상태를 전환 방지하기 위해 OnToggle 방법을 재정의 할 수

public class LockableToggleButton : ToggleButton 
{ 
    protected override void OnToggle() 
    { 
     if (!LockToggle) 
     { 
      base.OnToggle(); 
     } 
    } 

    public bool LockToggle 
    { 
     get { return (bool)GetValue(LockToggleProperty); } 
     set { SetValue(LockToggleProperty, value); } 
    } 

    // Using a DependencyProperty as the backing store for LockToggle. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty LockToggleProperty = 
     DependencyProperty.Register("LockToggle", typeof(bool), typeof(LockableToggleButton), new UIPropertyMetadata(false)); 
} 
+0

감사합니다. 나는 그것을 시도 할 것이다. –

+3

훌륭한 솔루션. – Ross

1

이것은 hackey,하지만 당신은 사용자 지정 코드를 원하지 않는 경우, 당신은 항상 속성을 "사용할 수 있습니다 IsHitTestVisible "을 선택하지 않으려면 IsHitTestVisible을 false로 설정하십시오. 그러나 컨트롤에 탭을 걸어 스페이스 바를 사용하여 토글 할 수 있습니다.

+0

또한 잠긴 상태에서 사용자가 토글하려고하면 소리가 나게하는 것이 바람직 할 수 있습니다. IsHitTestVisible을 사용하면이 작업을 수행 할 수 없습니다. – jpierson

+0

'IsTabStop = "False"'를 사용하여 사용자가 버튼으로 탭 이동하지 못하도록 할 수 있습니다. XAML에서 바로 수행 할 수 있고 MVVM과 친숙하며 사용자 지정 코드가 필요하지 않으므로이 솔루션을 사용하는 것이 더 좋습니다. 스타일을 여러 곳에 적용해야하는 경우 스타일을 사용할 수 있습니다. –

3

대신 라디오 버튼을 사용해 보셨습니까? 일반적으로 다른 것을 선택하지 않으면 선택을 해제 할 수 없습니다. 이미 그냥 BasedOn="{x:Type ToggleButton}" 만들어, 그것을 위해 Style이있는 경우,

<RadioButton Style="{StaticResource {x:Type ToggleButton}}"/> 

을 또는 : 또한 ToggleButton을 같이하는 스타일을 지정할 수 있습니다. Visual Studio Editor는 첫 번째 경우에 오류를 표시하지만 컴파일되고 제대로 작동합니다.

1

Thomas의 대답은 정상적으로 작동하지만 추가 종속성 속성이 필요하지 않습니다. OnToggle 메서드를 재정의하고 ViewModel의 IsChecked 바운드 속성을 변경할 수 있도록 ToggleButton에서 상속하는 클래스가 있으면 단추가 올바르게 업데이트됩니다.

XAML :

<myControls:OneWayFromSourceToTargetToggle x:Name="MyCustomToggleButton" 
              Command="{Binding Path=ToggleDoStuffCommand}" 
              CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self}}" 
              IsChecked="{Binding Path=ToggleIsCheckedConditionVar, 
                   Mode=OneWay}" 
              /> 

추가 ToggleButton의 등급 : true 또는 false로 뷰 모델 만 설정 부울 ToggleIsCheckedCondition에서 다음

public class OneWayFromSourceToTargetToggle : ToggleButton 
{ 
    /// <summary> 
    /// Overrides the OnToggle method, so it does not set the IsChecked Property automatically 
    /// </summary> 
    protected override void OnToggle() 
    { 
     // do nothing 
    } 
} 

. 좋은 MVVM 관행을 따르고 있기 때문에 좋은 방법입니다.

뷰 모델 :

public bool ToggleIsCheckedCondition 
{ 
    get { return _toggleIsCheckedCondition; } 
    set 
    { 
     if (_toggleIsCheckedCondition != value) 
     { 
     _toggleIsCheckedCondition = value; 
     NotifyPropertyChanged("ToggleIsCheckedCondition"); 
     } 
    } 
} 

public ICommand ToggleDoStuffCommand 
{ 
    get { 
     return _toggleDoStuffCommand ?? 
       (_toggleDoStuffCommand = new RelayCommand(ExecuteToggleDoStuffCommand)); 
     } 
} 

private void ExecuteToggleDoStuffCommand(object param) 
{ 
    var btn = param as ToggleButton; 
    if (btn?.IsChecked == null) 
    { 
     return; 
    } 
    // has not been updated yet at this point 
    ToggleIsCheckedCondition = btn.IsChecked == false; 

    // do stuff 

    } 
}