内联MultiBinding无法按预期工作 [英] Inline MultiBinding not working as expected

查看:113
本文介绍了内联MultiBinding无法按预期工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用

解决方案

首先,您的 MultiBinder 可以正常工作,因为您在问题中提供的内容没有进行任何修改.在运行时不会产生任何错误,并且会调用正确的构造函数.

问题是WPF设计器,众所周知,它有很多错误,在很多情况下都会产生错误,例如这种情况.当然,您可以忽略在设计器中看到的错误",但是这很烦人,而且如果忽略它们,您可能会错过真正的错误.

相反,我们可以找到设计师究竟在做错什么,然后尝试解决该问题.错误消息提供了一个线索,即在设计模式下传递给构造函数的转换器为null.然后我们可以像这样修复它:

 公共类MultiBinder:MultiBinding {public MultiBinder(BindingBase b1,BindingBase b2,对象转换器= null){Bindings.Add(b1);Bindings.Add(b2);Converter =转换器为IMultiValueConverter;CheckConverter();}public MultiBinder(BindingBase b1,BindingBase b2,BindingBase b3,对象转换器){Bindings.Add(b1);Bindings.Add(b2);Bindings.Add(b3);Converter =转换器为IMultiValueConverter;CheckConverter();}公共MultiBinder(BindingBase b1,BindingBase b2,BindingBase b3,BindingBase b4,对象转换器){Bindings.Add(b1);Bindings.Add(b2);Bindings.Add(b3);Bindings.Add(b4);Converter =转换器为IMultiValueConverter;CheckConverter();}私人无效CheckConverter(){如果(转换器== null&& DesignerProperties.GetIsInDesignMode(new DependencyObject())){//如果我们处于设计模式-馈送虚拟转换器,则无法调用wpf设计器Converter =新的DummyConverter();}}私有类DummyConverter:IMultiValueConverter {公共对象Convert(object []值,类型targetType,对象参数,CultureInfo文化){抛出新的NotSupportedException();}public object [] ConvertBack(对象值,Type [] targetTypes,对象参数,CultureInfo文化){抛出新的NotSupportedException();}}} 

此资料夹在设计器和运行时均不会产生错误.

I created an inline MultiBinding using this post as a reference. More specifically, I'm using Christian Myksvoll's answer for creating a custom binding. My class looks like this:

   public class MultiBinder : MultiBinding
   {

      public MultiBinder(BindingBase[] bindings, object converter)
      {
         foreach (BindingBase b in bindings)
         {
            Bindings.Add(b);
         }

         Converter = converter as IMultiValueConverter;
      }

      public MultiBinder(BindingBase b1, BindingBase b2, object converter)
      {
         Bindings.Add(b1);
         Bindings.Add(b2);

         Converter = converter as IMultiValueConverter;
      }

      public MultiBinder(BindingBase b1, BindingBase b2, BindingBase b3, object converter)
      {
         Bindings.Add(b1);
         Bindings.Add(b2);
         Bindings.Add(b3);

         Converter = converter as IMultiValueConverter;
      }

      public MultiBinder(BindingBase b1, BindingBase b2, BindingBase b3, BindingBase b4, object converter)
      {
         Bindings.Add(b1);
         Bindings.Add(b2);
         Bindings.Add(b3);
         Bindings.Add(b4);

         Converter = converter as IMultiValueConverter;
      }
   }

I added the first array constructor just to see if I could make it handle an unknown number of bindings, but I couldn't get the call to work. So, I removed it, and now I'm trying to use the 3 value constructor :

<MyControl IsEnabled="{util:MultiBinder 
                         {Binding Path=IsRequestedPriceControlEnabled}, 
                         {Binding Path=IsIndicative}, 
                         {StaticResource MultiBoolConverter}
                      }" />

It's giving me this error:

Cannot set MultiBinding because MultiValueConverter must be specified.

The converter I'm providing implements IMultiValueConverter and is being used without problem in a style block elsewhere. I can't use it in a style block for this purpose due to the sheer number of control types and variable conditions required.

Class Declaration: public class MultiBoolToBoolConverter : IMultiValueConverter
Resource: <util:MultiBoolToBoolConverter x:Key="MultiBoolConverter" />

The only thing I can figure is that it doesn't recognize that the 3rd parameter is the converter. I've tried tinkering with the IsEnabled content to explicitly set Converter like Discord's example (along with trimming down the class to only have a single constructor with 2 parameters), but that didn't work, either. That gives this error:

Unknown property 'Converter' for type 'MS.Internal.Markup.MarkupExtensionParser+UnknownMarkupExtension' encountered while parsing a Markup Extension.

My Question:

Has anyone made an inline multi-binding like this and know what I'm doing wrong?

Note: I'm using .NET 4.6, so I can use any other functionality if needed.


EDIT:

I still get the "Cannot set [...]" error above in the designer even with Evk's defaulting to null and using a dummy converter. But, it does run. I'm testing it with this:

CommandParameter="{util:MultiBinder {Binding Path=IsExpiriesComboBoxEnabled}, {Binding Path=IsIndicative}, {StaticResource MultiBoolConverter}}"

If I put a breakpoint in the MultiBinder, it goes into the 3 parameter overload (b1,b2,converter) correctly, and I can see the Converter being set to the MultiBoolConverter. So, I don't know why it's still giving the designer error.

SOLUTION:

The problem was a really, really stupid one. At some point after migrating the solution from VS2008 to VS2015, a XAML designer gave me an error or something and suggested disabling code execution, so I did. So, using the inline multibinder was confusing it since the converter wasn't being passed in. I had a hard time finding where to turn code execution back on, but once I did, it worked. So, the inline multibinding DOES work -- if it is being executed.

If you run into the same problem, here's the button that eluded me:

解决方案

First, your MultiBinder does work, as you provided it in your question without any modifications. It does not produce any errors at runtime and correct constructor is called.

Problem is WPF designer, which is known to be quite buggy and produce false errors in many cases, like this one. Of course you can just ignore that "error" you see in designer but it's quite annoying plus you can miss real errors if you would ignore them.

Instead, we can find what exactly designer does wrong and try to fix that. Error message provides a clue that converter which is passed in design mode to your constructor is null. Then we can fix it like this:

public class MultiBinder : MultiBinding {
    public MultiBinder(BindingBase b1, BindingBase b2, object converter = null) {
        Bindings.Add(b1);
        Bindings.Add(b2);

        Converter = converter as IMultiValueConverter;
        CheckConverter();
    }

    public MultiBinder(BindingBase b1, BindingBase b2, BindingBase b3, object converter) {
        Bindings.Add(b1);
        Bindings.Add(b2);
        Bindings.Add(b3);

        Converter = converter as IMultiValueConverter;
        CheckConverter();
    }

    public MultiBinder(BindingBase b1, BindingBase b2, BindingBase b3, BindingBase b4, object converter) {
        Bindings.Add(b1);
        Bindings.Add(b2);
        Bindings.Add(b3);
        Bindings.Add(b4);

        Converter = converter as IMultiValueConverter;
        CheckConverter();
    }

    private void CheckConverter() {            
        if (Converter == null && DesignerProperties.GetIsInDesignMode(new DependencyObject())) {
            // if we are in design mode - feed dummy converter which cannot be called to wpf designer
            Converter = new DummyConverter();
        }
    }

    private class DummyConverter : IMultiValueConverter {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) {
            throw new NotSupportedException();
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) {
            throw new NotSupportedException();
        }
    }
}

This binder does not produce errors both is designer and in runtime.

这篇关于内联MultiBinding无法按预期工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆