简体   繁体   中英

System.ArgumentNullException when Implementing base window class in WPF application

I'm implementing a base window class for a WPF application so a number of my windows can share code. Visual Studio will not allow a base window class in a WPF app to be defined using XAML, everything must be defined in codebehind.

Some things are simple, for example, the background of all forms can easily be set in C#. However, DataBinding in codebehind is more challenging than in XAML. I am trying to convert this working XAML code:

    <Window.BorderBrush>
        <Binding ElementName="Automator" Path="IsActive" Converter="{StaticResource IsActiveToBrushConverter}" UpdateSourceTrigger="PropertyChanged"/>
    </Window.BorderBrush>

Into C# for codebehind. I have converted this to the following:

        BindingOperations.SetBinding(
                BorderBrush,
                BorderBrushProperty,
                GetBinding("IsActive", new IsActiveToBrushConverter()));

For reference, GetBinding:

private Binding GetBinding(string path, IValueConverter converter, BindingMode binding = BindingMode.Default)
        {
            return new Binding(path)
            {
                Converter = converter,
                UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
                Source = this,
                Mode = binding
            };
        }

This code results in an exception: System.ArgumentNullException: 'Value cannot be null. Parameter name: target'. I thought I might be able to resolve this issue by setting the BorderBrush ahead of time, and then binding to it immediately after (GetSolidColorBrush is a local method that should be self-explanatory):

        BorderBrush = GetSolidColorBrush("#ff0000");
        BindingOperations.SetBinding(
                BorderBrush,
                BorderBrushProperty,
                GetBinding("IsActive", new IsActiveToBrushConverter()));

For reference, GetSolidColorBrush:

private SolidColorBrush GetSolidColorBrush(string colorString)
        {
            var color = (Color)ColorConverter.ConvertFromString(colorString);
            return new SolidColorBrush(color);
        }

While this code prevents the exception and appears to allow the binding to function (debug breakpoints confirm that the IsActiveToBrushConverter is being called when the form IsActive property changes), the BorderBrush property is not adjusted -- it stays red (the static color I set to prevent the ArgumentNullException). It seems when the BorderBrush is set to a static value, it overrides the value that the binding sets. I have also tried BorderBrush.SetCurrentValue in the hopes that this value can be overridden by the binding, but this results in the same ArgumentNullException as not setting it at all.

The expression

BindingOperations.SetBinding(
    BorderBrush,
    BorderBrushProperty,
    GetBinding("IsActive", new IsActiveToBrushConverter()));

means to set a Binding on the BorderBrush property of the object passed as first argument (ie the value of the Window's BorderBrush property). That makes no sense, because the object is a SolidColorBrush that does not have a BorderBrush property.

The correct way to set a Binding on the Window's BorderBrush property is

BindingOperations.SetBinding(
    this,
    BorderBrushProperty,
    GetBinding("IsActive", new IsActiveToBrushConverter()));

or to use the Window's SetBinding method:

SetBinding(
    BorderBrushProperty,
    GetBinding("IsActive", new IsActiveToBrushConverter()));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM