Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't use x:Bind with Converter in Window #4966

Open
alexdi220 opened this issue May 6, 2021 · 20 comments
Open

Can't use x:Bind with Converter in Window #4966

alexdi220 opened this issue May 6, 2021 · 20 comments
Labels
area-XamlWindow documentation An issue with existing documentation or a request for documenation of a new topic team-Markup Issue for the Markup team wpf-vs-winui-mismatch

Comments

@alexdi220
Copy link
Contributor

Describe the bug
Hi, I've tried to use the x:Bind with IValueConverter. But the project doesn't compile - CS1503 Argument 1: cannot convert from 'TestApp.MainWindow' to 'Microsoft.UI.Xaml.FrameworkElement'. Please take a look at the following code. What I do wrong?

Steps to reproduce the bug

<Window
    x:Class="TestApp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TestApp"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    <Grid RowDefinitions="Auto, *" x:Name="root">
        <Grid.Resources>
            <local:MyConverter x:Key="MyConverter"/>
        </Grid.Resources>
        <StackPanel Spacing="12"
                    Grid.Row="1">
            <TextBlock Text="{x:Bind MyProperty, Converter={StaticResource MyConverter}}"/>
        </StackPanel>
    </Grid>
</Window>
    public class MyConverter : IValueConverter {
        public object Convert(object value, Type targetType, object parameter, string language) => value;
        public object ConvertBack(object value, Type targetType, object parameter, string language) => value;
    }

    public sealed partial class MainWindow : Window {
        public MainWindow() {
            this.InitializeComponent();            
        }
        public string MyProperty { get; } = "Test";

Expected behavior

Screenshots
image

Version Info

NuGet package version:

[WinUI 3 - Project Reunion 0.5: 0.5.6]

Windows app type:

UWP Win32
Yes
Windows 10 version Saw the problem?
Insider Build (xxxxx)
October 2020 Update (19042) Yes
May 2020 Update (19041)
November 2019 Update (18363)
May 2019 Update (18362)
October 2018 Update (17763)
April 2018 Update (17134)
Fall Creators Update (16299)
Creators Update (15063)
Device form factor Saw the problem?
Desktop Yes
Xbox
Surface Hub
IoT

Additional context

@ghost ghost added the needs-triage Issue needs to be triaged by the area owners label May 6, 2021
@ranjeshj ranjeshj added the team-Markup Issue for the Markup team label May 11, 2021
@ranjeshj
Copy link
Contributor

@RealTommyKlein FYI

@RealTommyKlein
Copy link
Contributor

Thanks for the report. The root of your .xaml needs to be a FrameworkElement since the Xaml compiler expects to be able to use the FrameworkElement.Resources property to get its resource dictionary. Since Window isn't a FrameworkElement, the generated code breaks down.

Instead, you should move the UI logic (<Grid RowDefinitions="Auto, *" x:Name="root"> etc.) into its own UserControl, and then set that UserControl as the content of the Window.

@michael-hawker
Copy link
Collaborator

Yeah, I too keep getting tripped up that Window isn't a DependencyObject... it's a bit weird.

If the expectation that Window is supposed to just be the host like the implicit Frame created in App.xaml.cs for UWP apps, maybe the File -> New template for WinUI 3 should separate out the MainWindow as also having a MainPage class hosted by it already setup?

This would help lead developers to the proper constructs when building their app and set them up for success vs. having everyone start dumping UI in MainWindow and then getting frustrated.

I mean I really like how the MainWindow is more exposed compared to all the extra logic on Startup that was done in the UWP space, but it's super confusing and bare-bones template when trying to start building an app from afterwards without creating a new Page first.

@Wufus
Copy link

Wufus commented Sep 10, 2021

This would help lead developers to the proper constructs when building their app and set them up for success vs. having everyone start dumping UI in MainWindow and then getting frustrated.

I mean I really like how the MainWindow is more exposed compared to all the extra logic on Startup that was done in the UWP space, but it's super confusing and bare-bones template when trying to start building an app from afterwards without creating a new Page first.

But we have another problem: CustomTitleBar we can set only with XAML code in MainWindow.xaml, yes?
Using other UI in other page.xaml file will say No for united title with UI.

Best issue about i want to say #2124 with a lot of scrennsots

@qJake
Copy link

qJake commented Sep 11, 2021

Coming from a strictly WPF/.NET Framework background, and trying out WinUI 3.x for the first time... this is really non-intuitive, especially when trying to port multi-window applications.

I realize that there is a fundamental difference in how UWP apps behave versus how traditional multi-window applications behave, but there should be an elegant solution to this problem nonetheless.

@KWodarczyk
Copy link

Thanks for the report. The root of your .xaml needs to be a FrameworkElement since the Xaml compiler expects to be able to use the FrameworkElement.Resources property to get its resource dictionary. Since Window isn't a FrameworkElement, the generated code breaks down.

Instead, you should move the UI logic (<Grid RowDefinitions="Auto, *" x:Name="root"> etc.) into its own UserControl, and then set that UserControl as the content of the Window.

Thanks for the report. The root of your .xaml needs to be a FrameworkElement since the Xaml compiler expects to be able to use the FrameworkElement.Resources property to get its resource dictionary. Since Window isn't a FrameworkElement, the generated code breaks down.

Instead, you should move the UI logic (<Grid RowDefinitions="Auto, *" x:Name="root"> etc.) into its own UserControl, and then set that UserControl as the content of the Window.

Isn't the Grid the root element ? the converter is defined in grid resources

@lavinders
Copy link
Member

lavinders commented May 3, 2022

Can a sample / example be provided in WinUI docs (if recommendation is to restructure the xaml to expose a usercontrol in order to use a converter / static resource?) so people don't spend cycles figuring out why this simple thing is not working. I am trying to use a boolean to visibility converter and it is so time consuming this simple thing.

@krschau
Copy link
Contributor

krschau commented Jun 29, 2022

Can a sample / example be provided in WinUI docs

@gabbybilka

@krschau krschau added documentation An issue with existing documentation or a request for documenation of a new topic and removed needs-triage Issue needs to be triaged by the area owners labels Jun 29, 2022
@thecosmicmuffet
Copy link

Thanks for the report. The root of your .xaml needs to be a FrameworkElement since the Xaml compiler expects to be able to use the FrameworkElement.Resources property to get its resource dictionary. Since Window isn't a FrameworkElement, the generated code breaks down.
Instead, you should move the UI logic (<Grid RowDefinitions="Auto, *" x:Name="root"> etc.) into its own UserControl, and then set that UserControl as the content of the Window.

Thanks for the report. The root of your .xaml needs to be a FrameworkElement since the Xaml compiler expects to be able to use the FrameworkElement.Resources property to get its resource dictionary. Since Window isn't a FrameworkElement, the generated code breaks down.
Instead, you should move the UI logic (<Grid RowDefinitions="Auto, *" x:Name="root"> etc.) into its own UserControl, and then set that UserControl as the content of the Window.

Isn't the Grid the root element ? the converter is defined in grid resources

I think this is a worthwhile point. The auto-gen code successfully finds a Grid at the element where the resource is placed. It then passes '*this' (which is the Window) to SetConverterLookupRoot. When it could just set it as the target.as that it's using for the SetDataRoot call. It's not a documentation issue. It's a autogen code issue with an inconsistent use of the term 'root' in the code block. e.g.:

case 3: // MainWindow.xaml line 45
               {
                   auto element3 = target.as<::winrt::Microsoft::UI::Xaml::Controls::Grid>();
                   auto objBindings = std::make_unique<MainWindow_obj3_Bindings>();
                   objBindings->SetDataRoot(element3.DataContext()); // Here we are using the frameworkElement we found correctly as the 'dataRoot'
                   objBindings->SetConverterLookupRoot(*this); // Here we are inconsistently reverting to making the ConverterLookupRoot use *this, which is the Window

Refactoring code to avoid this autogen issue or making it about documentation seems like it's not very customer-focused. Why do we need to read more and refactor code, when this seems like a minor, and easily changeable portion of the generated code?

@omikhailov
Copy link

This is a bug in autogenerated code, of course, not a documentation issue. No one in their right mind creates a separate control for every page.

I would even say that it is a critical bug which requires few hours to fix it, but due to the fact that tags assigned to the task are misleading, I guess it will not be fixed until 2030.

@GuildOfCalamity
Copy link

GuildOfCalamity commented Mar 2, 2023

This is a big problem, how did you remove the ease of functionality that was binding in WPF/UWP and replace it with this??
I'm trying to use a boolean to visibility converter in my current project and cannot get it to work:
Argument 1: cannot convert from 'Demo.MainWindow' to 'Microsoft.UI.Xaml.FrameworkElement'
even though my converter and control is part of a Grid element.
I'm definitely not going to make some custom UserControl as a work-around to this issue (that never was an issue before), it needs to be addressed ASAP! Are you trying to make the framework more difficult or less difficult?
I understand that you're trying to abstract away the Window from the framework, but in doing that you need to provide basic functions... like WindowResize, WindowCenter, WindowMove, etc.

@ACGNnsj
Copy link

ACGNnsj commented May 14, 2023

This is definitely a problem. Why must I create a FrameworkElement instead of a Window?

@Konstantin-tr
Copy link

Since this is still not working, is there any plan to address this? Apart from this not being mentioned anywhere except for these bug reports, this is insanely impractical and the mentioned workaround is nothing short of a hack...

@Reza-Noei
Copy link

Hello Guys, Any plan to solve this issue ?

@GuildOfCalamity
Copy link

@Reza-Noei Unfortunately I don't think MS views this as a problem, and there will never be a "fix" since they have abstracted the Window object away from the Microsoft.UI.Xaml.FrameworkElement. I would suggest just using the MainWindow as a wrapper for a Frame/Page and then proceed as usual from there.

@Reza-Noei
Copy link

Reza-Noei commented Sep 9, 2023

@GuildOfCalamity ty for the answer. Sad for Microsoft 😢.
So they should remove it from the WinUI-3's Template Studio. That's so ridiculous 🤦‍♂️

@tinmac
Copy link

tinmac commented Oct 2, 2023

@RealTommyKlein

The work around suggests using a UserControl but I need to use a bool to vis converter in the TitleBar

The TitleBar cant take a UserControl so how can we do this?

@neelabo
Copy link

neelabo commented Dec 2, 2023

The more familiar you are with WPF, the more confused you will be.
Even if the error is due to a different base architecture, this error message gives no information for a solution.
I finally managed to get to the information here from the vast web, but those who can't get to it are leaving WinUI3.
This is very problematic.

@CodyLyttle
Copy link

This is very unintuitive for anyone familiar with WPF.
One option is to use traditional binding when a converter is required.

<Grid x:Name="Root">
    <TextBlock Text="{Binding Text, Converter={StaticResource MyConverter}}"/>
</Grid>

// Code Behind
Root.DataContext = vm;

@rdeetz
Copy link

rdeetz commented Jan 28, 2024

++ To all this. I am having this problem as well. It seems like both the generated code and the default template should be fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-XamlWindow documentation An issue with existing documentation or a request for documenation of a new topic team-Markup Issue for the Markup team wpf-vs-winui-mismatch
Projects
None yet
Development

No branches or pull requests