-
Notifications
You must be signed in to change notification settings - Fork 697
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
Two questions regarding porting WPF code to WinUI: Window Datacontext and Application.Current.Dispatcher #2687
Comments
@MikeHillberg @ryalanms or @oscarcabrero could one of you weigh in on question 1? The answer to 2 is to use DispatcherQueue.GetForCurrentThread().TryEnqueue() https://docs.microsoft.com/en-us/uwp/api/windows.system.dispatcherqueue.tryenqueue?view=winrt-19041#Windows_System_DispatcherQueue_TryEnqueue_Windows_System_DispatcherQueueHandler_ |
Window in WinUI isn't a FrameworkElement like it is in WPF, and so doesn't inherit the DataContext property. So you need to set the DataContext on the root element. It could potentially be added. But DataContext isn't used in WinUI as often as it is in WPF, because WinUI has x:Bind, which doesn't need it. (WinUI does still have Binding though.) |
|
OK thanks for pointers, will look at converting to x:Bind as that seems to be the preferred option. which in turn refers to my MainWindow resources to load the related view: Is this still possible or is there also a different/better approach? |
@Wigmund I did the exact same think. I converted a WPF app to WinUI Desktop app Preview.
In case you would like to switch to x:Bind you can start with a dependency property for your view model: {x:Bind ViewModel.Property} public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register(nameof(ViewModel),
typeof(MainViewModel),
typeof(MainPage),
new PropertyMetadata(null));
public MainViewModel ViewModel
{
get => GetValue(ViewModelProperty) as MainViewModel;
set => SetValue(ViewModelProperty, value);
} This still works: <DataTemplate x:DataType="viewModels:ProductViewModel"> with x:Binds inside the template the bindings are actually compile/design time safe. This was not present in WPF |
Thanks for the heads up. |
Compilation fails with a "property not found" when using
in the Application resource dictionary - is this expected? |
I see in your sample you are using a UserControl to bind the ViewModel to. I guess this is because Window is not a DependencyObject (FrameworkElement) so you can't create a dependency property on it. I was trying to create a MainViewModel for the MainWindow itself. I guess that isn't possible. Steve |
@abritabroad yes that's why I ended with a UserControl. I originally wanted to use PRISM, but it's not available for WinUI3. Currently it's only for WinUI 2. So I also wanted to start with (Shell(MainWindow).xaml/ShellViewModel(MainViewModel)) pair. It seems that I will have to use conditional compilation in my shared project in some cases, since there are at least three different namespaces (WPF, WinUI2/UWP, WinUI3) :( using System.Windows.Controls;
using Windows.UI.Xaml;
using Microsoft.UI.Xaml; protected override void InitializeShell(UIElement /*Window*/ shell)
{
shell.DataContext = shellViewModel;
base.InitializeShell(shell);
} |
@Wigmund I tried it in a UWP app and it didn't work there neither, so this is probably expected. I moved the datatemplate inside a separate resource dictionary and it worked. I was also hoping for minimal changes and even sharing of XAML, but different namespace declarations and so on won't enable this (WPF vs WinUI3): xmlns:views="clr-namespace:Joker.Sample.Views"
xmlns:views="using:Joker.Sample.Views" AFAIK it's not possible to use conditional compilation in a XAML file. |
Note that with x:Bind the source property doesn't need to be a DependencyProperty, it can be any C# property. To keep the markup/code the same, can you set the DataContext on the Window's root panel? That prevents the Window itself from binding to the data context, but works the same for anything below the panel. |
oh, that's good to know! My brain still thinks in WPF. Been on the web side for several years now. |
When trying to figure out why I was getting the following compilation error, Google brought me here.
As a WPF developer, the above error just consumed a couple hours of my day, in part because I allowed myself to become frustrated. I thought I would share the solution so that other developers who are led here by Google can find the answer. The problem occurs as @Wigmund stated, when you are using a DataType on a DataTemplate.
Although I tried to move the template all over the app, the final attempt was to keep it in a resource dictionary named DataTemplates.xaml. To stop the compilation error, I needed to add a class definition to the DataTemplates.xaml file and then create a partial class DataTemplates.xaml.cs to match. Even though I am still getting use to the UWP way of XAML vs WPF, I was aware that sometimes you had to have a backing '.cs' file for the XAML. However, I thought that you only needed that when using the 'x:Bind' markup extension. Apparently I was wrong because the above syntax won't even work in a UWP application. Update - using x:Bind in a Resource DictionaryI further learned that when you include a dictionary that has been defined as described above it is Important that you include it like the following. If you don't, InitializeComponent will not be called and x:Bind will not work! This is an easy mistake to make.
I will never make this mistake again! :) Hopefully this helps somebody. |
Closing this issue. Please @ me to reopen if you feel the questions here haven't been answered. |
I know it has been a while but using x:name on a WPF |
Using .Net 5 preview 4 and WinUI 3.0 preview, I'm experimenting porting WPF code and have encountered two questions:
The text was updated successfully, but these errors were encountered: