Alex141 / CalcBinding

Advanced WPF Binding which supports expressions in Path property and other features
Apache License 2.0
638 stars 79 forks source link

Bug report: Binding Error w Bool-To-Visibility & Template DataType #44

Closed metal450 closed 5 years ago

metal450 commented 7 years ago

I've come across what appears to be a bug when using multibindings with bool-to-visibility, where it reports binding errors for templates that shouldn't be applying (based on DataType). Here's code to repro:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication1"
    xmlns:c="clr-namespace:CalcBinding;assembly=CalcBinding"
    Title="MainWindow" Height="350" Width="525">
<StackPanel>

    <ContentControl x:Name="contentControl" Content="{Binding}">
        <ContentControl.Resources>

            <DataTemplate DataType="{x:Type local:ClassSimple}">
                <TextBlock>I am ClassSimple</TextBlock>
            </DataTemplate>

            <DataTemplate DataType="{x:Type local:ClassComplex}">
                <GroupBox>
                    <TextBlock>I am ClassComplex: <TextBlock Visibility="{c:Binding 'SomeProperty || SomeProperty2'}" /></TextBlock>
                </GroupBox>
            </DataTemplate>

        </ContentControl.Resources>
    </ContentControl>

    <Button Content="ClassSimple" Click="Click_ClassSimple"/>
    <Button Content="ClassComplex" Click="Click_ClassComplex"/>
</StackPanel>    
</Window>

And in CodeBehind:

public class ClassSimple { }
public class ClassComplex { public bool SomeProperty { get; set; } public bool SomeProperty2 { get; set; } }

private void Click_ClassSimple(object sender, RoutedEventArgs e)
{
    contentControl.DataContext = new ClassSimple();
}

private void Click_ClassComplex(object sender, RoutedEventArgs e)
{
    contentControl.DataContext = new ClassComplex();
}

If you click "ClassSimple," all is as expected. But if you click "ClassComplex" then "ClassSimple," you'll get:

Binding error: one of source fields is Unset, return null
System.Windows.Data Error: 5 : Value produced by BindingExpression is not valid for target property.; Value='<null>' MultiBindingExpression:target element is 'TextBlock' (Name=''); target property is 'Visibility' (type 'Visibility')

Oddly, if you remove the GroupBox in the ClassComplex template, the binding error goes away. Likewise, it goes away if you just bind to SomeProperty or SomeProperty2 (not both).

Alex141 commented 7 years ago

Thank you for detailed description, I will see it soon

Alex141 commented 7 years ago

I have analyzed this problem. It looks like a strange WPF behaviour or WPF bug. It occured only when using MultiBinding and outer container in DataTemplate. The point is that when you change DataContext of ContentPresenter, two bindings (instead of one) are updated: for previous DataTemplate (strange) and for new DataTemplate. Old MultiBinding is updated with DependencyProperty.Unset values for all pathes.

However, I note that this error should not adversely affect on system, isn't it? I have an idea to make a small correction and add support of FallbackValue, for such cases, so after that correction message in outout window will not appear

Alex141 commented 7 years ago

37

metal450 commented 7 years ago

I note that this error should not adversely affect on system, isn't it?

Yup the behavior does appear as it should. The problem is just that in the real application, there are a large number of such bindings, so whenever you perform an action that causes this to happen (i.e. switching tabs in a tabbed interface), the app grinds to a halt while the Output Pane catches up with the output - & actual log messages used for debugging get lost among the pages of errors. So yeah, just something to get rid of the error messages would be awesome :) 👍

Alex141 commented 7 years ago

Ok, I understand you :) I'll do it as soon as available time

metal450 commented 7 years ago

Awesome, looking forward to it! :)

metal450 commented 5 years ago

Just wanted to check in if you ever had a chance to look at this...?

Alex141 commented 5 years ago

I'm so sorry, I just forgot that I wanted to solve this issue in next iteration in 2017 :( Good, that you remind about it :) I include this issue in current iteration

metal450 commented 5 years ago

Just out of curiosity: is there any easy workaround I might be able to use in the interim? I recently had to change a core part of my application to use DataType-based templates, and the result is so many of these debug messages that it actually locks up VS when performing certain actions (i.e. changing doc tabs, which re-binds all the tool controls & prints errors for almost all of them). The application does function - it just gets so bogged down by all the logging that it's become extremely difficult to debug :/

Thanks for any thoughts :)

Alex141 commented 5 years ago

I'm afraid you can only disable all tracing, it will turn off messages from calcBinding lib also:

System.Diagnostics.Trace.Listeners.Clear()

But all traces from your application will be turned off also :)

You can disable only wpf binding messages, so first of two messages will stop appearing in the output window:

Binding error: one of source fields is Unset, return null

Tools->Options->Debugging->Output Window -> WPF Trace Settings -> Data binding - off

but as I understand, you have huge of messages and probably it will not help much

I'm working on normal solution 👍

metal450 commented 5 years ago

Alright yeah, I was more thinking/hoping along the lines of maybe something I could hack in the calcbinding code to disable it for just that library, so I could still see valid messages from elsewhere. If not then not tho - I suppose I'll just anxiously await the official fix :)

On Wed, Jun 26, 2019, 14:44 Alex141 notifications@github.com wrote:

I'm afraid you can only disable all tracing, it will turn off messages from calcBinding lib also:

System.Diagnostics.Trace.Listeners.Clear()

But all traces from your application will be turned off also :)

You can disable only wpf binding messages, so first of two messages will stop appearing in the output window:

Binding error: one of source fields is Unset, return null

Tools->Options->Debugging->Output Window -> WPF Trace Settings -> Data binding - off

but as I understand, you have huge of messages and probably it will not help much

I'm working on normal solution 👍

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/Alex141/CalcBinding/issues/44?email_source=notifications&email_token=AAOKLIKC7IYA5BDOISU3URTP4PPNHA5CNFSM4C464PO2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODYU5CLY#issuecomment-506057007, or mute the thread https://github.com/notifications/unsubscribe-auth/AAOKLIKKSGP567FLAY75TCLP4PPNHANCNFSM4C464POQ .

Alex141 commented 5 years ago

Sorry, but no solutions :( I will try to release the update quicker

Alex141 commented 5 years ago

version 2.5.2 is released, nuget package - https://www.nuget.org/packages/CalcBinding/2.5.2

Check please that traces from calcBinding don't appear in output, and if everyting ok I close issue :)

metal450 commented 5 years ago

Woo hoo, looks like that did it! Safe to close - thanks so much for the quick turnaround :)