2010-03-30 24 views
9

Tôi có danh sách ToggleButtons đang được sử dụng làm ItemTemplate trong ListBox tương tự như this answer bằng cách sử dụng chế độ MultiSelect của Listbox. Tuy nhiên tôi cần đảm bảo ít nhất một mục luôn được chọn.Làm thế nào tôi có thể ngăn ToggleButton bị Toggled mà không thiết lập IsEnabled

Tôi có thể nhận được hành vi thích hợp từ ListBox bằng cách thêm một mục trở lại vào bộ sưu tập SelectedItems của ListBox trên sự kiện ListBox.SelectionChanged nhưng ToggleButton của tôi vẫn di chuyển ra khỏi trạng thái chuyển đổi của nó vì vậy tôi nghĩ rằng tôi cần dừng nó sớm hơn quá trình.

Tôi muốn làm điều đó mà không cần thiết lập IsEnabled = "False" trên nút cuối cùng Được chọn vì tôi muốn ở lại với phong cách hình ảnh được bật mà không phải làm lại mẫu nút của tôi. Bất kỳ ý tưởng?

Trả lời

28

Bạn có thể ghi đè lên OnToggle phương pháp để ngăn chặn chuyển đổi qua lại nhà nước, bằng cách không gọi việc thực hiện cơ sở:

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

Cảm ơn. Tôi sẽ thử. –

+3

Giải pháp tuyệt vời. – Ross

1

Đây là hackey, nhưng nếu bạn không muốn mã tùy chỉnh bạn luôn có thể sử dụng bất động sản " IsHitTestVisible ", khi bạn không muốn chúng bỏ chọn nó, chỉ cần đặt IsHitTestVisible bằng false. Tuy nhiên, họ có thể tab để kiểm soát và chuyển đổi nó bằng cách sử dụng thanh không gian.

+0

Cũng có thể mong muốn tạo âm thanh * ding * âm thanh khi người dùng cố gắng chuyển đổi âm thanh trong khi nó bị khóa. Sử dụng IsHitTestVisible sẽ không cho phép một người đạt được điều này. – jpierson

+0

Bạn có thể sử dụng 'IsTabStop =" False "' để giữ cho người dùng không bị nhét vào nút. Tôi thích giải pháp này qua câu trả lời được chấp nhận vì nó có thể được thực hiện ngay trong XAML, là MVVM thân thiện và không yêu cầu bất kỳ mã tùy chỉnh nào. Một kiểu có thể được sử dụng nếu bạn cần áp dụng nó ở nhiều nơi. –

3

Bạn đã thử sử dụng RadioButton thay thế chưa? Nó thường không thể được bỏ chọn mà không chọn một số khác. Nó cũng có thể được theo kiểu để trông giống như một ToggleButton:

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

Hoặc, nếu bạn đã có một Style cho nó, chỉ cần làm cho nó BasedOn="{x:Type ToggleButton}". Lưu ý rằng Visual Studio Editor cho thấy một lỗi trong trường hợp đầu tiên, nhưng nó biên dịch và hoạt động tốt.

1

Câu trả lời của Thomas hoạt động tốt, nhưng bạn thậm chí không cần thêm thuộc tính phụ thuộc. Nút của bạn sẽ cập nhật chính xác nếu bạn có lớp kế thừa từ ToggleButton để bạn có thể ghi đè lên phương thức OnToggle, và bạn thay đổi thuộc tính ràng buộc IsChecked trên ViewModel.

XAML:

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

Added ToggleButton Class:

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

Sau đó, trong ViewModel chỉ cần đặt bool ToggleIsCheckedCondition là đúng hoặc sai. Đây là một cách hay để làm điều đó bởi vì bạn đang theo dõi các thực hành MVVM tốt.

ViewModel:

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 

    } 
} 
Các vấn đề liên quan