dotnet / wpf

WPF is a .NET Core UI framework for building Windows desktop applications.
MIT License
7.08k stars 1.17k forks source link

System.Windows.Markup.XamlParseException: 'Constructor on type 'System.Windows.Forms.TextBoxAutoCompleteSourceConverter' not found.' #5845

Open fo40225 opened 2 years ago

fo40225 commented 2 years ago

內部例外狀況 1: MissingMethodException: Constructor on type 'System.Windows.Forms.TextBoxAutoCompleteSourceConverter' not found.

 **Expected behavior:**
 No crash.
 **Minimal repro:**
```xaml
<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <WindowsFormsHost>
            <wf:TextBox AutoCompleteSource="CustomSource"/>
        </WindowsFormsHost>
    </Grid>
</Window>
singhashish-wpf commented 2 years ago

@RussKie The implementation of the converter is in winforms, could you please look at this issue once?

miloush commented 2 years ago

The TextBox.AutoCompleteSource has a TextBoxAutoCompleteSourceConverter converter applied. However, the converter does not have parameterless constructor, and therefore is unusable in XAML.

The TextBoxAutoCompleteSourceConverter actually derives from EnumConverter which itself does not have parameterless constructor. The XamlValueConverter which is in charge of creating the converter has a special case for converters of type EnumConverter, however, it does not support converters derived from it. WinForms has couple of such converters, although the others are much less likely to appear in XAML.

One solution is to ignore custom value converters on enum properties and always create an instance of EnumConverter for them (i.e. relax the converter type check from == to inherits from). Another one is to contractually expect any type converter deriving from EnumConverter to have a constructor that expects one Type parameter. Both these solutions would break any well designed existing enum converters that have parameterless constructors.

The cleanest fix is probably on WinForms side, to provide a parameterless constructor for this converter. Most of the converters were designed for one particular enum, so it should be possible to call the base constructor with that enum type.

(Also note that I couldn't find any documentation on type converters stating the parameterless constructor requirement for use in XAML.)

RussKie commented 2 years ago

I'm not sure what kind of help you're expecting. You're trying to use Windows Forms types in WPF scenarios, and this has never been officially supported.

The cleanest fix is probably on WinForms side, to provide a parameterless constructor for this converter. Most of the converters were designed for one particular enum, so it should be possible to call the base constructor with that enum type.

I'm not convinced this is true. The right way would be for WPF to provide the necessary converter and decorations on the TextBox control.

miloush commented 2 years ago

You're trying to use Windows Forms types in WPF scenarios, and this has never been officially supported.

The existence of WindowsFormsHost and documentation like https://docs.microsoft.com/en-us/dotnet/desktop/wpf/advanced/walkthrough-hosting-a-windows-forms-control-in-wpf-by-using-xaml suggests otherwise. Perhaps you are suggesting WinForms have not agreed to this contract and as such it is up to WPF to fix any incompatibilities?

My suggestion of adding parameterless constructor to the converter(s) is a trivial solution that has zero performance impact on both WPF and WinForms side. If that is not an option on WinForms side and WPF is willing to take either performance hit on supporting this case or dependence on this particular WinForms type, then there are other ways to fix this.

I don't see how WPF can provide decorations on WinForms' TextBox control, can you elaborate? What the user can do to workaround the problem is either derive a custom control from TextBox and get rid of the type converter, or do not use XAML to set this property.