2010-03-30 56 views
9

我使用列表框的MultiSelect模式,有一個列表框中的ToggleButton被用作列表框中的ItemTemplate,類似於this answer。不過,我需要確保至少選擇一個項目。如何防止ToggleButton未設置IsEnabled而被切換

我可以通過在ListBox.SelectionChanged事件中將一個項目添加到ListBox的SelectedItems集合中來獲得ListBox的正確行爲,但我的ToggleButton仍然移出它的切換狀態,所以我認爲我需要在早期停止它該過程。

我想在沒有在最後一個按鈕上設置IsEnabled =「False」的情況下進行選擇,因爲我希望保留Enabled視覺樣式而不必重做我的按鈕模板。有任何想法嗎?

回答

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

感謝。我會試一試。 – 2010-03-31 15:19:02

+3

偉大的解決方案。 – Ross 2012-06-13 13:41:39

1

這是hackey,但如果你不希望自定義代碼,你可以總是使用屬性「 IsHitTestVisible「,當你不希望他們取消選中它時,只需將IsHitTestVisible設置爲false即可。但是,他們可以選中控件並使用空格鍵切換它。

+0

另外,當用戶在鎖定時嘗試切換聲音時,可能會發出聲音* ding *聲音。使用IsHitTestVisible將不允許人們實現這一點。 – jpierson 2011-02-02 18:14:18

+0

您可以使用'IsTabStop =「False」'也保持用戶不跳轉到按鈕。我比較接受的答案更喜歡這個解決方案,因爲它可以在XAML中正確完成,對MVVM友好,並且不需要任何自定義代碼。如果您需要將它應用於多個位置,則可以使用樣式。 – 2016-09-23 17:37:06

3

您是否嘗試過使用RadioButtons?如果不選擇另一個,通常無法取消選擇。它也可以樣式看起來像一個切換按鈕:

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

或者,如果你已經有這方面的Style,只是使它BasedOn="{x:Type ToggleButton}"。請注意,Visual Studio編輯器在第一種情況下顯示錯誤,但它編譯並正常工作。

1

托馬斯的答案工作正常,但你甚至不需要額外的依賴屬性。如果您有從ToggleButton繼承的類,則您的按鈕將正確更新,因此您可以重寫OnToggle方法,並更改ViewModel上的IsChecked綁定屬性。

的XAML:

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

添加切換按鈕類:

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 
    } 
} 

然後在視圖模型只設置布爾ToggleIsCheckedCondition爲true或false。這是一個很好的方法,因爲您遵循了良好的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 

    } 
}