三状态CheckBox绑定自身默认值

时间:2013-11-18 21:18:43

标签: .net wpf xaml

如果设置了IsChecked绑定,如何将三态复选框默认为null? FallbackValue =“{x:Null}”似乎不起作用?我试图让复选框默认为null而不是false。

<CheckBox IsThreeState="True">
    <CheckBox.IsChecked>
        <Binding RelativeSource="{RelativeSource Self}"
                 Path="IsChecked"
                 FallbackValue="{x:Null}"
                 UpdateSourceTrigger="Explicit">
            <Binding.ValidationRules>
                <Validators:StandardValidators />
            </Binding.ValidationRules>
        </Binding>
    </CheckBox.IsChecked>
</CheckBox>

更新1: 要明确触发我使用的验证:

    private void SaveChanges()
    {
         if (!this.ValidateForm(this.GridContainingCheckboxes))
         {
              return;
         {

         var myObject = new CustomObject();
         myObject.InspectedElement = myCheckbox.IsChecked;

         // Save Stuff Here
    }

    private bool ValidateForm(DependencyObject obj)
    {
        var result = true;

        foreach (var checkBox in this.ChildrenOfType<CheckBox>())
        {
            var bindingExpression = BindingOperations.GetBindingExpression(checkBox, ToggleButton.IsCheckedProperty);

            if (bindingExpression != null)
            {
                bindingExpression.UpdateSource();
            }
        }

        if (!this.IsValid(obj))
        {
            result = false;
        }

        return result;
    }

    private bool IsValid(DependencyObject obj)
    {
        return !Validation.GetHasError(obj) && LogicalTreeHelper.GetChildren(obj).OfType<DependencyObject>().All(child => this.IsValid(child));
    }

更新2:

public class StandardValidators : ValidationRule
{
    /// <summary>
    /// Initializes a new instance of the <see cref="StandardValidators"/> class.
    /// </summary>
    public StandardValidators()
    {
        this.AllowNull = false;
    }

    /// <summary>
    /// Gets or sets ErrorMessage.
    /// </summary>
    public string ErrorMessage { get; set; }

    /// <summary>
    /// Gets or sets a value indicating whether AllowNull.
    /// </summary>
    public bool AllowNull { get; set; }

    /// <summary>
    /// Gets or sets a value indicating whether IsBoolean.
    /// </summary>
    public bool IsBoolean { get; set; }

    /// <summary>
    /// The main validator.
    /// </summary>
    /// <param name="value">
    /// The value.
    /// </param>
    /// <param name="cultureInfo">
    /// The culture info.
    /// </param>
    /// <returns>
    /// The validation result.
    /// </returns>
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        var result = new ValidationResult(true, null);

        if (!this.AllowNull)
        {
            if (this.IsBoolean && (value as bool?) == null)
            {
                this.ErrorMessage = "Cannot Be Null";
                return new ValidationResult(false, this.ErrorMessage);
            }
        }

        return result;
    }
}

2 个答案:

答案 0 :(得分:1)

FallbackValue无效的原因是因为CheckBoxes IsChecked具有有效值(false),因此它将使用该值而不是FallbackValue

基于您使用OverrideMetadata附加的示例似乎在您的解决方案中正常工作,下面是我使用的代码。

public MainWindow()
{
    CheckBox.IsCheckedProperty.OverrideMetadata(typeof(CheckBox), new FrameworkPropertyMetadata((bool?)null));
    InitializeComponent();

    // if you want to show validation errors on load.
    Loaded += (s, e) => this.ValidateForm(this.MainGrid);
}

答案 1 :(得分:1)

您可以在EventTriggermsdn)中设置的默认值:

<CheckBox x:Name="chb" IsThreeState="True">
...
    <CheckBox.Triggers>
        <EventTrigger RoutedEvent="CheckBox.Loaded">
            <BeginStoryboard>
                <Storyboard>
                    <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetName="chb"
                            Storyboard.TargetProperty="IsChecked">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Null}" />
                    </ObjectAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </CheckBox.Triggers>
</CheckBox>

修改

您可以使用 System.Windows.Interactivity 程序集来设置默认值。

创建帮助器类以设置属性:

public class SetterAction : TriggerAction<DependencyObject>
{
    public SetterAction()
    {
        Setters = new List<Setter>();
    }

    public List<Setter> Setters { get; set; }

    protected override void Invoke(object parameter)
    {
        foreach (var item in Setters)
        {
            AssociatedObject.SetValue(item.Property, item.Value);
        }
    }
}

XAML代码:

<CheckBox x:Name="InspectOverallUnitToggleButton" IsThreeState="True">
    <CheckBox.IsChecked>
        <Binding RelativeSource="{RelativeSource Self}"
                 Path="IsChecked"
                 FallbackValue="{x:Null}"
                 UpdateSourceTrigger="Explicit">
            <Binding.ValidationRules>
                <Validators:StandardValidators IsBoolean="True"/>
            </Binding.ValidationRules>
        </Binding>
    </CheckBox.IsChecked>              
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <i:EventTrigger.Actions>
                <local:SetterAction>
                    <local:SetterAction.Setters>
                        <Setter Property="CheckBox.IsChecked" Value="{x:Null}" />
                    </local:SetterAction.Setters>
                </local:SetterAction>
            </i:EventTrigger.Actions>
        </i:EventTrigger>                  
    </i:Interaction.Triggers>
</CheckBox>

i的位置:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
您可以在Microsoft Expression Blend 3 SDK(link)中找到

System.Windows.Interactivity.dll 程序集。