unoplatform / Uno.Themes

This library is designed to help you use the Material, Fluent or Cupertino design system with the Uno Platform
https://platform.uno
Apache License 2.0
168 stars 31 forks source link

[TextBox][WinUI] Failed to assign LeadingIcon #1286

Open eriklimakc opened 9 months ago

eriklimakc commented 9 months ago

Current behavior

Windows (WinUI) specific.

When setting LeadingIcon to TextBox the error "Failed to assign LeadingIcon" occurs.

Obs.: And even if LeadingIcon is not set an unhandled excpetion is thrown.

How to reproduce it (as minimally and precisely as possible)

  1. Create an Uno app with latest packages (or download -> LeadingIcon-Repro.zip)
  2. Add the following code and uncomment one at a time
  3. Run on Windows
 <!--UNCOMMENT TO SEE THE UNHANDLED EXCEPTION-->

 <!--<TextBox Text="test"
     PlaceholderText="Enter your name:">
 </TextBox>-->

 <!--UNCOMMENT TO SEE THE LeadingIcon ERROR-->

 <!--<TextBox Style="{StaticResource OutlinedTextBoxStyle}"
        Text="test">
   <um:ControlExtensions.LeadingIcon>
     <SymbolIcon Symbol="Favorite" />
   </um:ControlExtensions.LeadingIcon>
 </TextBox>-->

Environment

Nuget Package:

Package Version(s):

Affected platform(s):

Anything else we need to know?

Xiaoy312 commented 9 months ago

winappsdk and sttached property..:

<Setter Property="um:ControlExtensions.TrailingIcon" Value="{x:Null}" />
<Setter Property="local:ControlHelper.Asd" Value="Qwe" />
<Setter Property="local:ControlHelper.AsdIcon" Value="{x:Null}" />

<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="TextBox">
            <StackPanel x:Name="Root">

                <void:Border Tag="X" void:Visibility="{Binding Path=(um:ControlExtensions.TrailingIcon), RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource MaterialNullToCollapsedConverter}, FallbackValue=Collapsed, TargetNullValue=Collapsed}">
                    <Button Content="{Binding Path=(um:ControlExtensions.TrailingIcon), RelativeSource={RelativeSource TemplatedParent}}"
                            void:Command="{Binding Path=(um:ControlExtensions.TrailingCommand), RelativeSource={RelativeSource TemplatedParent}}"
                            void:Visibility="{Binding Path=(um:ControlExtensions.IsTrailingIconVisible), RelativeSource={RelativeSource TemplatedParent}}"/>
                </void:Border>

                <void:ContentControl Tag="O" Content="{TemplateBinding um:ControlExtensions.TrailingIcon}" />
                <void:ContentControl Tag="X" Content="{Binding Path=(um:ControlExtensions.TrailingIcon), RelativeSource={RelativeSource TemplatedParent}}" />
                <void:ContentControl Tag="X" Content="{Binding Path=(um:ControlExtensions.TrailingIcon), RelativeSource={RelativeSource Mode=TemplatedParent}}" />

                <ContentControl Tag="O" Content="{TemplateBinding local:ControlHelper.Asd}" />
                <ContentControl Tag="O" Content="{Binding Path=(local:ControlHelper.Asd), RelativeSource={RelativeSource TemplatedParent}}" />
                <ContentControl Tag="O" Content="{Binding Path=(local:ControlHelper.Asd), RelativeSource={RelativeSource Mode=TemplatedParent}}" />

                <!-- note: both work, just not both at same time (since UIElement can nested under 1 parent at a time) -->
                <!--<ContentControl Tag="O" Content="{TemplateBinding local:ControlHelper.AsdIcon}" />-->
                <!--<ContentControl Tag="O" Content="{Binding Path=(local:ControlHelper.AsdIcon), RelativeSource={RelativeSource TemplatedParent}}" />-->

                <Button Tag="O" Content="{TemplateBinding um:ControlExtensions.TrailingIcon}" />
                <void:Button Tag="X" Content="{Binding Path=(um:ControlExtensions.TrailingIcon), RelativeSource={RelativeSource TemplatedParent}}" />

^ for attached properties from local assemblies, binding and template-binding all work. ^ for attached properties from foreign assemblies, binding doesnt work, but template-binding works. __^ note: we can't use template binding with converter... so it is not a valid workaround.

Xiaoy312 commented 9 months ago

good ole microsoft/microsoft-ui-xaml#6388 ^ we did tried to use Jerome's workaround with default {x:Null}, which doesnt work... ^ we also tried to use this other workaround from toolkit, which also doesnt work..: https://github.com/unoplatform/uno.toolkit.ui/blob/main/samples/Uno.Toolkit.Samples/Uno.Toolkit.Samples.Shared/Content/Controls/DrawerFlyoutSamplePage.xaml#L25

Xiaoy312 commented 9 months ago

@jeromelaban given the disparity between attached dp defined locally and from package, could we have failed to generate/missed copying certain files in the package that winappsdk needs?

jeromelaban commented 9 months ago

Run the WinUI app using the native debugger, it may give you more information about the issue (make sure to be on 1.4 latest)

eriklimakc commented 9 months ago

I got the following , but I guess this doesn't offer much context:

image

image

cc @jeromelaban @Xiaoy312

jeromelaban commented 9 months ago

You'll need to look at the output window to get meaningful information.

eriklimakc commented 9 months ago
Microsoft.ui.xaml.dll!00007FFB78FF8841: 80004005 - Unspecified error
Microsoft.ui.xaml.dll!00007FFB78F9EFB0: 80004005 - Unspecified error
Exception thrown at 0x00007FFC9F96565C (KernelBase.dll) in LeadingIcon.Windows.exe: WinRT originate error - 0x80004005 : 'System.Runtime.InteropServices.COMException'.
Microsoft.ui.xaml.dll!00007FFB78FC512F: 80004005 - Unspecified error

These are the last logs from the output before the app crashes. I couldn't find any relevant information from the output, but I am attaching it here so you guys can take a look.

Output-Debug.txt

@Xiaoy312 @jeromelaban

Xiaoy312 commented 9 months ago
full stack trace ``` 104 WinRT.ExceptionHelpers.ThrowExceptionForHR.__Throw|39_0(int hr) Line 146 103 WinRT.ExceptionHelpers.ThrowExceptionForHR(int hr) Line 135 102 ABI.Microsoft.UI.Xaml.IFrameworkElementOverridesMethods.MeasureOverride(WinRT.IObjectReference _obj, Windows.Foundation.Size availableSize) Line 14 101 Microsoft.UI.Xaml.FrameworkElement.MeasureOverride(Windows.Foundation.Size availableSize) Line 692 100 Microsoft.UI.Xaml.FrameworkElement.Microsoft.UI.Xaml.IFrameworkElementOverrides.MeasureOverride(Windows.Foundation.Size availableSize) Line 697 99 ABI.Microsoft.UI.Xaml.IFrameworkElementOverrides.Do_Abi_MeasureOverride_0(nint thisPtr, Windows.Foundation.Size availableSize, Windows.Foundation.Size* result) Line 33 98 [Native to Managed Transition] 97 [Inline Frame] DirectUI::FrameworkElementGenerated::MeasureOverrideProtected(ABI::Windows::Foundation::Size) Line 1086 96 DirectUI::FrameworkElement::MeasureOverrideFromCore(CFrameworkElement * nativeTarget, float inWidth, float inHeight, float * outWidth, float * outHeight) Line 246 95 [Inline Frame] FxCallbacks::FrameworkElement_MeasureOverride(CFrameworkElement *) Line 742 94 CFrameworkElement::MeasureCore(XSIZEF availableSize, XSIZEF & desiredSize) Line 1534 93 CUIElement::MeasureInternal(XSIZEF availableSize) Line 3997 92 CUIElement::Measure(XSIZEF availableSize) Line 3859 91 CContentPresenter::MeasureOverride(XSIZEF availableSize, XSIZEF & desiredSize) Line 851 90 CFrameworkElement::MeasureCore(XSIZEF availableSize, XSIZEF & desiredSize) Line 1551 89 CUIElement::MeasureInternal(XSIZEF availableSize) Line 3997 88 CUIElement::Measure(XSIZEF availableSize) Line 3859 87 CControl::MeasureOverride(XSIZEF availableSize, XSIZEF & desiredSize) Line 417 86 [Inline Frame] CFrameworkElement::MeasureOverrideForPInvoke(XSIZEF) Line 1429 85 [Inline Frame] CoreImports::FrameworkElement_MeasureOverride(CFrameworkElement *) Line 546 84 [Inline Frame] DirectUI::FrameworkElement::MeasureOverrideImpl(ABI::Windows::Foundation::Size) Line 203 83 DirectUI::FrameworkElementGenerated::MeasureOverride(ABI::Windows::Foundation::Size availableSize, ABI::Windows::Foundation::Size * pReturnValue) Line 1067 82 DirectUI::ContentControl::MeasureOverride(ABI::Windows::Foundation::Size availableSize, ABI::Windows::Foundation::Size * pReturnValue) Line 41 81 [Inline Frame] DirectUI::FrameworkElementGenerated::MeasureOverrideProtected(ABI::Windows::Foundation::Size) Line 1090 80 DirectUI::FrameworkElement::MeasureOverrideFromCore(CFrameworkElement * nativeTarget, float inWidth, float inHeight, float * outWidth, float * outHeight) Line 246 79 [Inline Frame] FxCallbacks::FrameworkElement_MeasureOverride(CFrameworkElement *) Line 742 78 CFrameworkElement::MeasureCore(XSIZEF availableSize, XSIZEF & desiredSize) Line 1534 77 CUIElement::MeasureInternal(XSIZEF availableSize) Line 3997 76 CUIElement::Measure(XSIZEF availableSize) Line 3859 75 CUIElement::Measure(XSIZEF availableSize) Line 3909 74 CUIElement::Measure(XSIZEF availableSize) Line 3909 73 CUIElement::Measure(XSIZEF availableSize) Line 3909 72 CUIElement::Measure(XSIZEF availableSize) Line 3909 71 CUIElement::Measure(XSIZEF availableSize) Line 3909 70 CUIElement::Measure(XSIZEF availableSize) Line 3909 69 CUIElement::Measure(XSIZEF availableSize) Line 3909 68 CUIElement::Measure(XSIZEF availableSize) Line 3909 67 CUIElement::Measure(XSIZEF availableSize) Line 3909 66 CUIElement::Measure(XSIZEF availableSize) Line 3909 65 CUIElement::Measure(XSIZEF availableSize) Line 3909 64 CXamlIslandRoot::MeasureOverride(XSIZEF availableSize, XSIZEF & desiredSize) Line 806 63 CFrameworkElement::MeasureCore(XSIZEF availableSize, XSIZEF & desiredSize) Line 1551 62 CUIElement::MeasureInternal(XSIZEF availableSize) Line 3997 61 CUIElement::Measure(XSIZEF availableSize) Line 3859 60 CUIElement::Measure(XSIZEF availableSize) Line 3909 59 CUIElement::Measure(XSIZEF availableSize) Line 3909 58 CLayoutManager::UpdateLayout(unsigned int controlWidth, unsigned int controlHeight) Line 291 57 CCoreServices::NWDrawTree(HWWalk * pHWWalk, CWindowRenderTarget * pRenderTarget, VisualTree * pVisualTree, bool forceRedraw, bool * pFrameDrawn) Line 6109 56 CCoreServices::NWDrawMainTree(CWindowRenderTarget * pIRenderTarget, bool forceRedraw, bool * pFrameDrawn) Line 5909 55 CWindowRenderTarget::Draw(CCoreServices * forceRedraw, bool pFrameDrawn, bool *) Line 129 54 CXcpBrowserHost::OnTick() Line 341 53 CXcpDispatcher::Tick() Line 1306 52 CXcpDispatcher::OnReentrancyProtectedWindowMessage(HWND__ * msg, unsigned int lParam, unsigned __int64) Line 908 51 [Inline Frame] CXcpDispatcher::ProcessMessage(HWND__ *) Line 758 50 CXcpDispatcher::WindowProc(HWND__ * hwnd, unsigned int msg, unsigned __int64 wParam, __int64 lParam) Line 715 49 CDeferredInvoke::DispatchQueuedMessage(bool * dispatchedWork, bool * hasMoreWork) Line 213 48 CXcpDispatcher::MessageTimerCallback() Line 1393 47 [Inline Frame] CXcpDispatcher::MessageTimerCallbackStatic(void *) Line 1381 46 [Inline Frame] CXcpDispatcher::Init::__l68::::operator()(ABI::Microsoft::UI::Dispatching::IDispatcherQueueTimer *) Line 403 45 Microsoft::WRL::Details::DelegateArgTraits,IInspectable *>::*)(ABI::Microsoft::UI::Dispatching::IDispatcherQueueTimer *,IInspectable *)>::DelegateInvokeHelper,ABI::Windows::Foundation::ITypedEventHandler,Microsoft::WRL::FtmBase>,`CXcpDispatcher::Init'::`68':: &,1,ABI::Microsoft::UI::Dispatching::IDispatcherQueueTimer *,IInspectable *>::Invoke(ABI::Microsoft::UI::Dispatching::IDispatcherQueueTimer * , IInspectable * ) Line 245 44 Microsoft::WRL::Details::DelegateArgTraits,struct IInspectable *>::*)(struct Microsoft::UI::Dispatching::IDispatcherQueueTimer *,struct IInspectable *)>::DelegateInvokeHelper,struct Windows::Foundation::ITypedEventHandler,class Microsoft::WRL::FtmBase>,class ,-1,struct Microsoft::UI::Dispatching::IDispatcherQueueTimer *,struct IInspectable *>::Invoke(struct Microsoft::UI::Dispatching::IDispatcherQueueTimer *,struct IInspectable *) Unknown 43 Microsoft::WRL::InvokeTraits<-2>::InvokeDelegates,struct Windows::Foundation::ITypedEventHandler >(class ,class Microsoft::WRL::Details::EventTargetArray *,class Microsoft::WRL::EventSource,struct Microsoft::WRL::InvokeModeOptions<-2> > *) Unknown 42 Microsoft::UI::Dispatching::DispatcherQueueTimer::TimerCallback(void *) Unknown 41 CFlat::SehSafe::Execute<>() Unknown 40 Microsoft::CoreUI::Dispatch::TimeoutHandler::ImportAdapter$(class CFlat::Box$1 > *) Unknown 39 Microsoft::CoreUI::Dispatch::TimeoutManager::Callback_OnDispatch(void) Unknown 38 Microsoft::CoreUI::Dispatch::Dispatcher::Callback_DispatchNextItem(class Microsoft::CoreUI::Dispatch::DispatchItem *) Unknown 37 Microsoft::CoreUI::Dispatch::Dispatcher::Callback_DispatchLoop(enum Microsoft::CoreUI::Dispatch::RunnablePriorityMask) Unknown 36 Microsoft::CoreUI::Dispatch::EventLoop::Callback_RunCoreLoop(enum Microsoft::CoreUI::Dispatch::RunMode) Unknown 35 Microsoft::CoreUI::Dispatch::UserAdapter::DrainCoreMessagingQueue(enum Microsoft::CoreUI::Dispatch::UserAdapter$UserPriority,void * *) Unknown 34 Microsoft::CoreUI::Dispatch::UserAdapter::OnUserDispatch(bool,enum Microsoft::CoreUI::Dispatch::UserAdapter$UserPriority,void * *) Unknown 33 Microsoft::CoreUI::Dispatch::UserAdapter::OnUserDispatchRaw(enum Microsoft::CoreUI::Dispatch::UserAdapter$UserPriority,bool,void * *) Unknown 32 Microsoft::CoreUI::Dispatch::UserAdapter::DoWork(struct HWND__ *,enum Microsoft::CoreUI::Dispatch::UserAdapter$UserPriority,bool) Unknown 31 Microsoft::CoreUI::Dispatch::UserAdapter::HandleDispatchNotifyMessage(struct HWND__ *,unsigned __int64,__int64) Unknown 30 Microsoft::CoreUI::Dispatch::UserAdapter::WindowProc(struct HWND__ *,unsigned int,unsigned __int64,__int64) Unknown 29 UserCallWinProcCheckWow() Unknown 28 DispatchClientMessage() Unknown 27 __fnDWORD() Unknown 26 KiUserCallbackDispatcherContinue() Unknown 25 NtUserGetMessage() Unknown 24 GetMessageW() Unknown 23 DirectUI::FrameworkApplication::RunDesktopWindowMessageLoop() Line 1267 22 DirectUI::FrameworkApplication::StartDesktop() Line 238 21 [Inline Frame] DirectUI::FrameworkApplicationFactory::StartImpl(ABI::Microsoft::UI::Xaml::IApplicationInitializationCallback *) Line 183 20 DirectUI::FrameworkApplicationFactory::Start(ABI::Microsoft::UI::Xaml::IApplicationInitializationCallback * pCallback) Line 789 19 [Managed to Native Transition] 18 ABI.Microsoft.UI.Xaml.IApplicationStaticsMethods.Start(WinRT.IObjectReference _obj, Microsoft.UI.Xaml.ApplicationInitializationCallback callback) Line 18 17 Microsoft.UI.Xaml.Application.Start(Microsoft.UI.Xaml.ApplicationInitializationCallback callback) Line 251 16 LeadingIcon.Program.Main(string[] args) Line 31 15 [Native to Managed Transition] 14 [Inline Frame] coreclr_t::execute_assembly(int) Line 109 13 run_app_for_context(const hostpolicy_context_t & context, int argc, const wchar_t * * argv) Line 256 12 run_app(const int argc, const wchar_t * * argv) Line 285 11 corehost_main(const int argc, const wchar_t * * argv) Line 426 10 execute_app(const std::wstring & impl_dll_dir, corehost_init_t * init, const int argc, const wchar_t * * argv) Line 145 09 `anonymous namespace'::read_config_and_execute(const std::wstring & host_command, const host_startup_info_t & host_info, const std::wstring & app_candidate, const std::unordered_map>,known_options_hash,std::equal_to,std::allocator>>>> & opts, int new_argc, const wchar_t * * new_argv, host_mode_t mode, const bool is_sdk_command, wchar_t * out_buffer, int buffer_size, int * required_buffer_size) Line 532 08 fx_muxer_t::handle_exec_host_command(const std::wstring & host_command, const host_startup_info_t & host_info, const std::wstring & app_candidate, const std::unordered_map>,known_options_hash,std::equal_to,std::allocator>>>> & opts, int argc, const wchar_t * * argv, int argoff, host_mode_t mode, const bool is_sdk_command, wchar_t * result_buffer, int buffer_size, int * required_buffer_size) Line 1007 07 fx_muxer_t::execute(const std::wstring host_command, const int argc, const wchar_t * * argv, const host_startup_info_t & host_info, wchar_t * result_buffer, int buffer_size, int * required_buffer_size) Line 578 06 hostfxr_main_startupinfo(const int argc, const wchar_t * * argv, const wchar_t * host_path, const wchar_t * dotnet_root, const wchar_t * app_path) Line 62 05 exe_start(const int argc, const wchar_t * * argv) Line 240 04 wmain(const int argc, const wchar_t * * argv) Line 311 03 [Inline Frame] invoke_main() Line 90 02 __scrt_common_main_seh() Line 288 01 BaseThreadInitThunk() Unknown 00 RtlUserThreadStart() Unknown ```
stack trace captured by the thrown exception ``` 05 at WinRT.ExceptionHelpers.g__Throw|39_0(Int32 hr) in WinRT\ExceptionHelpers.cs:line 146 04 at WinRT.ExceptionHelpers.ThrowExceptionForHR(Int32 hr) in WinRT\ExceptionHelpers.cs:line 148 03 at ABI.Microsoft.UI.Xaml.IFrameworkElementOverridesMethods.MeasureOverride(IObjectReference _obj, Size availableSize) in ABI.Microsoft.UI.Xaml\IFrameworkElementOverridesMethods.cs:line 13 02 at Microsoft.UI.Xaml.FrameworkElement.MeasureOverride(Size availableSize) in Microsoft.UI.Xaml\FrameworkElement.cs:line 692 01 at Microsoft.UI.Xaml.FrameworkElement.Microsoft.UI.Xaml.IFrameworkElementOverrides.MeasureOverride(Size availableSize) in Microsoft.UI.Xaml\FrameworkElement.cs:line 697 00 at ABI.Microsoft.UI.Xaml.IFrameworkElementOverrides.Do_Abi_MeasureOverride_0(IntPtr thisPtr, Size availableSize, Size* result) in ABI.Microsoft.UI.Xaml\IFrameworkElementOverrides.cs:line 33 ```

HResult = -2147467259 (0x80004005) // E_FAIL element measured at frame 99 or 00 is MainPage exception.Data:

[Description] = No such interface supported
[RestrictedDescription] = No such interface supported
[RestrictedErrorReference] =
[RestrictedCapabilitySid] =
[__RestrictedErrorObjectReference] = WinRT.ExceptionHelpers+__RestrictedErrorObject
[__HasRestrictedLanguageErrorObject] = False
kazo0 commented 9 months ago

@jeromelaban I don't see anything helpful in the stacktrace unless you see something?

Youssef1313 commented 8 months ago

I'll take a look

eriklimakc commented 8 months ago

@Youssef1313 , here's a repro with the style/template that may facilitate the investigation... The style/template is basically a copy of the MaterialOutlinedTextBoxStyle defined in my branch (dev/ERLI/TextBox-Icons).

LeadingIcon.zip

cc @kazo0

Youssef1313 commented 8 months ago

I got nowhere investigating this 😕

Xiaoy312 commented 8 months ago

based on my previous research: https://github.com/unoplatform/Uno.Themes/issues/1286#issuecomment-1826145345 just as a workaround: we can probably just stick to {TemplateBinding}, and use a custom control that takes either an IconElement or an CustomIcon(name to be discussed) that is a DependencyObject with properties like (Icon, IsVisible, Command,...). This way we can bypass the types of binding that would fail on WinAppSdk and use TemplateBinding on control's local depenncy-property for {icon,visibility,command}.

CustomIconPresenter.Icon.changed += (s, e) => {
    var sender = s as CustomIconPresenter ?? throw ...;
    // todo: clear previous values
    if (e.NewValue is CustomIcon custom) {
        sender.SetBinding(CustomIconPresenter.IconElementProperty, new Binding(nameof(CustomIcon.Icon)) { RelativeSource=TemplatedParent });
        // todo: same for IsVisible and Command...
    else if (e.NewValue is IconElement) {
        sender.IconElement = icon;