3

I have faced strange behavior in wpf. When ever I try to pass x:Array as converter parameter to my converter I get this error. and designer view shows error instead of my controls.

this error only happens when I do this in Style:

property 'System.Windows.Data.Binding'.'ConverterParameter' is null.

While my program does compile and run successfully without any problems, but its really annoying in design view because I cant see my controls, I hope you can find the reason of this problem and give solution.

I have simplified what I had and following is the way to reproduce this problem (so this is just example, not exactly what I have).

You can reproduce this problem simply by doing these steps:

Step 1 : make a user control with this content. (ContentControl is just example. this happens to any control that has template property.)

<UserControl.Resources> <!-- will tell you in next step --> </UserControl.Resources>
<Grid>
    <ContentControl Style="{StaticResource MyStyle}"></ContentControl>
</Grid>

Step2: Now you have to create MyStyle in your UserControl resource (or any global resource you like).

<UserControl.Resources>
    <Style x:Key="MyStyle" TargetType="ContentControl">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ContentControl">
                    <Border Background="Black" Width="16" Height="16">

                        <!-- if I remove these error will be gone -->
                        <Border.Resources>
                            <converters:ThicknessConverter x:Key="ThicknessConverter"/>
                            <x:Array x:Key="ThicknessModifier" Type="Thickness">
                                <!--Thickness Coefficient-->
                                <Thickness>-0.5</Thickness>
                                <!--Thickness Offset-->
                                <Thickness>0,2</Thickness>
                            </x:Array>
                        </Border.Resources>

                        <Border.Margin>
                            <Binding Path="Width"
                                         RelativeSource="{RelativeSource Self}"
                                         Converter="{StaticResource ThicknessConverter}"
                                         ConverterParameter="{StaticResource ThicknessModifier}"/>
                        </Border.Margin>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</UserControl.Resources>

Step3: Create the converter, I haven't tested but I think this will happen to any converter. because my converter doesn't throw exception.

/// <summary>
/// returns thickness and sets given value to uniform length,
/// array of thickness with length of two can be passed as parameter, 
/// first element of parameter is used for thickness multiplication and second element is used for addition.
/// note that multiplication has higher priority.
/// </summary>
[ValueConversion(typeof(double), typeof(Thickness), ParameterType = typeof(Thickness[]))]
public sealed class ThicknessConverter : IValueConverter
{
    [NotNull]
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is double)
        {
            var val = (double)value;
            var param = parameter as Thickness[];

            if (param?.Length >= 1)
            {
                if (param.Length >= 2)
                {
                    return new Thickness(
                        val*param[0].Left + param[1].Left,
                        val*param[0].Top + param[1].Top,
                        val*param[0].Right + param[1].Right,
                        val*param[0].Bottom + param[1].Bottom);
                }
                else
                {
                    return new Thickness(
                        val*param[0].Left,
                        val*param[0].Top,
                        val*param[0].Right,
                        val*param[0].Bottom);
                }

            }
            else
            {
                if (parameter is Thickness)
                {
                    var mul = (Thickness)parameter;
                    return new Thickness(
                        val*mul.Left,
                        val*mul.Top,
                        val*mul.Right,
                        val*mul.Bottom);
                }
                return new Thickness(val);
            }
        }
        else return default(Thickness);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Step4: Put your user control in main window. and run the program. and I hope you see the error. I did reproduce this in my computer so I think you should get that too. How can I fix this problem?

M.kazem Akhgary
  • 18,645
  • 8
  • 57
  • 118
  • Have u look up to this Q? http://stackoverflow.com/a/26275926/7167572 There are also some answers that might give u a hint. – Tatranskymedved Jan 29 '17 at 15:04
  • @Tatranskymedved Yes. ive seen that. It doesn't work. Interesting thing is that if I close the designer view and run my program, the error goes away... but as soon as I open designer view the error comes in, any idea? :( – M.kazem Akhgary Jan 29 '17 at 15:12
  • 1
    In designer the solution is being compiled for designer context (namespace starting by default with `d:` ). I have run into same problem (& I guess every1 does), but I have not checked any solution yet. – Tatranskymedved Jan 29 '17 at 15:14
  • 1
    Thanks for your time, I was able to fix this using custom list instead of `x:Array` @Tatranskymedved – M.kazem Akhgary Jan 29 '17 at 16:56

1 Answers1

1

I was able to go around with this issue by using Collection<Thickness> instead of x:Array, I still don't know why x:Array has this weird problem. So I created a wrapper class for list of Thickness.

public class ThicknessList : Collection<Thickness>
{
}

Again another thing is that I must put this thickness list resource in resource container of Style, if I put it in resource container of Border I get this weird error

Missing key value on object

BTW Here is the fix to Style. (the converter also needed some changes because the passed parameter is not array anymore, but that's not important here.)

<Style x:Key="MyStyle" TargetType="ContentControl">

    <Style.Resources> <!-- must put resource here -->

        <converters:ThicknessConverter x:Key="ThicknessConverter"/>

        <ns:ThicknessList x:Key="ThicknessModifier"> <!-- wrapper list instead of x:Array -->
            <!--Thickness Coefficient-->
            <Thickness>-0.5</Thickness>
            <!--Thickness Offset-->
            <Thickness>0,2</Thickness>
        </ns:ThicknessList>
    </Style.Resources>

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ContentControl">
                <Border Background="Black" Width="16" Height="16">
                    <Border.Margin>
                        <Binding Path="Width"
                                     RelativeSource="{RelativeSource Self}"
                                     Converter="{StaticResource ThicknessConverter}"
                                     ConverterParameter="{StaticResource ThicknessModifier}"/>
                    </Border.Margin>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

M.kazem Akhgary
  • 18,645
  • 8
  • 57
  • 118