【问题标题】:Three State CheckBox Binding Self Default Value三态复选框绑定自身默认值
【发布时间】:2013-12-02 05:08:01
【问题描述】:

如何在设置 IsChecked 绑定时将三态复选框默认为空? 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;
    }
}

【问题讨论】:

  • 所以没有任何东西绑定到 CheckBox 你只是希望它显示为默认值?如果这个复选框没有绑定到任何东西,它会做什么?

标签: .net wpf xaml


【解决方案1】:

你可以在EventTrigger(msdn)中设置的默认值:

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

System.Windows.Interactivity.dll 程序集,您可以在 Microsoft Expression Blend 3 SDK (link).

【讨论】:

  • 这会阻止用户编辑 CheckBox 的值。
  • @BitOriented 再次检查我的答案 :)
【解决方案2】:

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

【讨论】:

  • 这似乎不会让 UpdateSource() 触发并触发验证规则。
  • 你想做什么?如果复选框未绑定到您要验证的任何内容。
  • 用户与复选框进行了交互,赋值为真或假,但不为空。默认情况下它需要为空,因为要进行检查,用户必须做出选择。
  • 这里是一个测试项目的链接。验证(红色高亮是我想要的,也是我想要的。)dropbox.com/s/x8sxq42s0v7d7bz/ToggleButtonTest.zip
  • 您可以覆盖 IsChecked 的元数据以显示为空,上面添加了示例
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多