【问题标题】:WPF Property Data binding to negate the propertyWPF 属性数据绑定以否定属性
【发布时间】:2011-02-04 13:06:30
【问题描述】:

有什么方法可以在运行时更改 WPF 数据绑定中的属性值。假设我的 TextBox 绑定到 IsAdmin 属性。无论如何我可以将 XAML 中的属性值更改为 !IsAdmin。

我只是想否定这个属性,所以 Valueconverter 可能有点过头了!

注意:不使用 ValueConverter

【问题讨论】:

    标签: wpf data-binding


    【解决方案1】:

    您可以使用IValueConverter

    [ValueConversion(typeof(bool), typeof(bool))]
    public class InvertBooleanConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            bool original = (bool)value;
            return !original;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            bool original = (bool)value;
            return !original;
        }
    }
    

    然后你会像这样设置你的绑定:

    <TextBlock Text="{Binding Path=IsAdmin, Converter={StaticResource boolConvert}}" />
    

    像这样添加资源(通常在您的用户控件/窗口中):

    <local:InvertBooleanConverter  x:Key="boolConvert"/>
    

    根据评论进行编辑:

    如果您出于某种原因想要避免使用值转换器(尽管我觉得这是最合适的地方),您可以直接在您的 ViewModel 中进行转换。只需添加如下属性:

    public bool IsRegularUser
    {
         get { return !this.IsAdmin; }
    }
    

    但是,如果您这样做,请确保您的 IsAdmin 属性设置器也为“IsRegularUser”和“IsAdmin”引发 PropertyChanged 事件,以便 UI 相应更新。

    【讨论】:

    • 其实我应该在不使用ValueConverter的情况下提到
    • 你不认为对于一个简单的否定操作来说工作量太大了!
    • @azamsharp:我编辑给你另一个选择 - 但不,我没有,主要是因为它是可重用代码。制作转换器后,您可以在代码库中的任何位置将其用于所有 !bool 转换。
    • 对于 valueconverter,这里是您需要使用的命名空间:using System.Windows.Data; using System.Globalization;
    【解决方案2】:

    如果您特别想在 XAML 端执行此操作(我不确定原因,除非您有 100 次类似的否定操作)只有两种方法 1)使用 IValueConverter 2)编写 XAML 标记扩展(这个小任务的工作量太大了:))

    那么另一种明显的方法是在您的 ViewModel 中编写另一个属性,它可以返回 IsAdmin 属性的 Negative。

    【讨论】:

      【解决方案3】:

      您可以编写一个 ValueConverter 在返回之前自动否定输入。请查看BenCon's blog,了解价值转换器的简短阅读。

      【讨论】:

        【解决方案4】:

        您不能绑定到 !Property,但您可以使用适当的 IValueConverter 创建一个新的 Binding,并在运行时更改整个 Binding。关键是 BindingOperations 类,它允许您更改特定 DependencyProperty 上的绑定。

            public static void InvertBinding(DependencyObject target, DependencyProperty dp)
            {
                //We'll invert the existing binding, so need to find it
                var binding = BindingOperations.GetBinding(target, dp);
                if (binding != null)
                {
                    if (binding.Converter != null)
                        throw new InvalidOperationException("This binding already has a converter and cannot be inverted");
                    binding.Converter = new InvertingValueConverter(); //This would be your custom converter
        
                    //Not sure if you need this step, but it will cause the binding to refresh
                    BindingOperations.SetBinding(target, dp, binding);
                }
            }
        

        这应该给你一个大致的想法;我不会将其用于生产代码,因为您可能希望将其概括为切换转换器或在运行时需要更改的任何其他内容。您还可以通过创建一个您绑定到的封装此“切换”逻辑的新属性来完全避免更改绑定。最后一个选项可能是最好的。

        【讨论】: