默认情况下,WPF ToggleButton 或 CheckBox(继承 ToggleButton)没有某种 ReadOnly 属性来阻止用户更改值。
一项技术在于设置
IsHitTestVisible="False"
和Focusable="False"
。
我认为我也可以实现将
IsChecked
属性绑定到 get
仅访问器。
class SomeViewModel
{
public bool Checked => true;
}
<CheckBox IsChecked="{Binding Checked, Mode=OneWay}">
但不幸的是,这不起作用,用户仍然可以更改 CheckBox 值...
不幸的是,在这种情况下,当用户更改值时,绑定会不同步。
下面的解决方案包括在用户更改值时始终刷新绑定。
public class ToggleButtonEx
{
public static readonly DependencyProperty IsReadOnlyProperty = DependencyProperty.RegisterAttached(
"IsReadOnly", typeof(bool), typeof(ToggleButtonEx), new PropertyMetadata(default(bool), OnPropertyChanged));
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is not ToggleButton toggleButton)
throw new InvalidOperationException($"This property may only be set on {nameof(ToggleButton)}.");
if ((bool)e.NewValue)
{
toggleButton.Checked += OnCheckChanged;
toggleButton.Unchecked += OnCheckChanged;
}
else
{
toggleButton.Checked -= OnCheckChanged;
toggleButton.Unchecked -= OnCheckChanged;
}
}
private static void OnCheckChanged(object sender, RoutedEventArgs e)
{
var checkedBinding = ((CheckBox)sender).GetBindingExpression(ToggleButton.IsCheckedProperty);
checkedBinding?.UpdateTarget();
}
public static void SetIsReadOnly(DependencyObject element, bool value)
{
element.SetValue(IsReadOnlyProperty, value);
}
public static bool GetIsReadOnly(DependencyObject element)
{
return (bool)element.GetValue(IsReadOnlyProperty);
}
}
<CheckBox IsChecked="{Binding Checked, Mode=OneWay}" ns:ToggleButtonEx.IsReadOnly="True">