XAML Design Time Preview for SwapChainPanel Element - xaml

So if I'm using a SwapChainPanel element in the XAML designer, I get a design-time error saying the element can't be created. I see this out of the box with the SwapChainPanel sample app from Microsoft. In Visual Studio 2013.3 I see an ugly "Cannot create an instance of "D3DPanel"." in the Design view for Scenario1.xaml.
I was wondering if there were a way to provide fallback data for this element so I see something in the designer and in Blend. I've found some examples for designer data for data-bound controls, but so far nothing for DirectX.
Edit: here's the stack trace from the designer in the Scenario1.xaml file from the SwapChainPanel demo. We seem to be able to create SwapChainPanels themselves, but when there's a custom C# class like D3DPanel, it chokes:
at Microsoft.Expression.Platform.InstanceBuilders.InstanceBuilderOperations.InstantiateType(Type type, Boolean supportInternal)
at Microsoft.Expression.Platform.InstanceBuilders.ClrObjectInstanceBuilder.InstantiateTargetType(IInstanceBuilderContext context, ViewNode viewNode)
at Microsoft.Expression.WindowsXamlPlatform.InstanceBuilders.GridInstanceBuilder.InstantiateTargetType(IInstanceBuilderContext context, ViewNode viewNode)
at Microsoft.Expression.Platform.InstanceBuilders.ClrObjectInstanceBuilder.Instantiate(IInstanceBuilderContext context, ViewNode viewNode)
at Microsoft.Expression.WindowsXamlPlatform.InstanceBuilders.FrameworkElementInstanceBuilder.Instantiate(IInstanceBuilderContext context, ViewNode viewNode)
at Microsoft.Expression.Platform.InstanceBuilders.ViewNodeManager.CreateInstance(IInstanceBuilder builder, ViewNode viewNode)
The offending XAML element is something like <renderer:D3DPanel x:Name="DirectXPanel1" Height="300" Width="300" />.

I opened a Microsoft Connect ticket for this behavior, but it was closed a no fix.

Related

MAUI: Unable to add an event handler via XAML if the event is internal

I found an unexpected XAML parser behavior. Here is a page from a MAUI project:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MauiApp1"
x:Class="MauiApp1.MyPage">
<local:MyView MyEvent="MyView_MyEvent" />
</ContentPage>
local:MyView is:
namespace MauiApp1;
class MyView: View
{
public event EventHandler MyEvent;
}
Pay attention to the event's public modifier. This is a fully working project until I change the modifier to internal. The page and MyView are entities of the same assembly, so the modifier change should have no affect on the app. However, it causes the LoadFromXaml method called from MyPage.InitializeComponent to throw a XamlParseException. With the internal modifier, I can still successfully add the event handler via C#, but not via XAML.
I decided to find out if this behavior is inherent in XAML in principle. In fact, this proved not to be the case. For example, WPF doesn't mind adding handlers to internal events via XAML.
Therefore, I would like to know: is this a bug from the MAUI developers or am I missing something?
When changing the modifier to Private, it'll also throw a XamlParseException.And this is a known issue Private EventHandlers throw an exception on XAML-defined custom control in Github, you can follow up it.
Furthermore, I notice you have reported a new issue on Github: https://github.com/dotnet/maui/issues/12566 and you can follow up it.

How do I access resource defined in App.xaml from OnLaunched?

I'm using the MVVM pattern with MVVM Light. I have a ViewModelLocator defined in App.xaml which holds all the ViewModels which are bound to from the Views using Blend.
I have an AppViewModel which basically contains all the important global info for my app, like user preferences. AppViewModel is instantiated by ViewModelLocator, which is in turn, instantiated by app.xaml.
The trouble is, I need to access AppViewModel from inside OnLaunched, however, at this stage of the application lifecycle, it appears app.xaml has not yet instantiated its declared resources. It appears to only do this after a Frame.Navigate().
I need to access AppViewModel because I have to inspect the properties on there in order to work out which Page to load. Hence it's a chicken-and-egg situation.
If I separately instantiate AppViewModel inside OnLaunched, then I can access AppViewModel, but then ViewModelLocator gets instantiated twice which causes problems with my IoC.
Is there a way of manually instantiating items declared inside app.xaml? Or is there a way to get app.xaml to load its resources before presenting a UI?
Or am I doing this wrong? Generally speaking, I regard the application to be the view model layer and the views essentially observe that... so hence I need the ViewModels available before I present any UI.
XAML:
<Application.Resources>
<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
</Application.Resources>
Code:
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
var vml = App.Current.Resources["Locator"] as ViewModelLocator; // exception raised
Exception:
WinRT information: Cannot find a resource with the given key.
thanks
How about you instantiate the ViewModelLocator when you first need it and then add it to Application.Resources once Application.Resources is otherwise initialized or whenever you need? You don't need to add key value pairs to the ResourceDictionaries in XAML always.

Understanding how to map events in xaml

I don't know C# events very well so I have difficulties in understanding some code I found in internet
Inside the code behind of a view file there is the following method:
public void SavingMesBoxClosedHandler(object sender, object args)
The DisplayMessageBox class is derived form FrameworkElement and defines the following event:
public delegate void MessageBoxClosedHandler(object sender, object args);
public event MessageBoxClosedHandler DialogClosed;
Inside the xaml of the view:
<DisplayMessageBoxDemo:DisplayMessageBox
// some dependency properties here
DialogClosed="SavingMesBoxClosedHandler"/>
I thought I could use only dependency properties, while DialogClosed is an event.
Which is the magic to map a method of the view to an event in DisplayMessageBox class using only its name ?
Why don't I have to use a binding ?
Is there an easy way to assign a viewmodel method as the event handler of DialogClose ?
May be I didn't use the correct terms in my last question. To put in other words I want to call a method inside my viewmodel, not in the view as in the example I reported above.
You don't have to use only dependency properties in XAML. You can use normal properties just as well. Dependency properties are a necessity when you use DataBinding, as you point out. In the case you mention there seems to be no need to use DataBinding because you will not use different handlers depending on your DataContext. If you want to stick to the MVVM pattern and keep the event handling logic in your view model, you can use EventTrigger: http://www.kunal-chowdhury.com/2010/11/using-eventtrigger-in-xaml-for-mvvm-no.html

Troubleshooting Win8 Apps: When are my XAML-defined Page fields initialized?

I'm trying the MVVM pattern and I've run into a problem.
Here's how I instantiate my model:
<common:LayoutAwarePage
...
...(omitted boiler plate generated lines here)
...
...
mc:Ignorable="d">
<common:LayoutAwarePage.DataContext>
<local:TextGameClientModel x:Name="textGameClientModel"/>
</common:LayoutAwarePage.DataContext>
But when I try to use it, I get a NullReferenceException because this.textGameClientModel is NULL:
public MainPage()
{
this.InitializeComponent();
this.textGameClientModel.runsPublished += textGameClientModel_runsPublished;
}
I've also tried the same line in the Page's OnNavigateTo handler, and also in the OnLoaded handler, but with the same result.
Where is the right place to hook up my event handler?
(Please don't let my code-behind in an MVVM project distract you from the question. My use of a RichTextBox has forced me to color outside the lines a little.)
I actually wrote an answer about the WPF Creation Steps fairly recently, however that's not the problem in this case.
In this case, you are setting the DataContext in your XAML, however that's not the same as setting the textGameClientModel property
You need to do something like this to set the property equal to your DataContext first
this.textGameClientModel = this.DataContext as GameClientModel;
or simply cast your DataContext as your class to setup the event
((GameClientModel)this.DataContext).runsPublished += textGameClientModel_runsPublished;
As a side note, I never recommend hardcoding the DataContext into a UserControl like you have. By doing so, you are preventing any other DataContext from getting passed to the UserControl, which kind of defeats one of the biggest advantages of WPF/MVVM, which is having separate UI and data layers.

ShowDialog a RadWindow with MVVMLight

I have a functional MVVM patterned SL app with a RadWindow (essentially a ChildWindow), that I would like to remove the code-behind in my view that shows the window using its ShowDialog. Both the main view and the window is bound to the same ViewModel if that helps.
The button has both a ViewModel command using a MVVMLight RelayCommand to handle setting state as well as the event handler in the View.
The ultimate solution/pattern will be reused 20+ times so something better than code-behind would be great.
Thoughts?
private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
{
var window = new RadWindowTest.Controls.ChildWindow1();
window.Closed += new System.EventHandler<Telerik.Windows.Controls.WindowClosedEventArgs>(window_Closed);
window.ShowDialog();
}
In this case I would suggest you implement DialogService. This service you can inject into your view model, for testing you will have to inject an instance that does not depend on the view, thus maintaining testability. You can use the ViewModelLocator to make this service available to your application.
Another approach would be to implement a ViewBase class that implements an interface that allows you to display the dialog. This interface is now used by the ViewModel to display a dialog. Again to test you need to provide a different implementation of the interface. A sample can be found here.
Both ideas revolve around the same concept of factoring out the function that shows the dialog. In order to strictly de-couple the View and the ViewModel you will have to think about how the ViewModel specifies which dialog has to be shoen, and how the dialog resut or dialog model is returned to the calling ViewModel.
Which approach is better is open to your judgement. Personally I prefer the first approach as I do not have to inherit the views from a common base class.
PS: Use a command to get to the point in your ViewModel where you want to show the dialog. Using a dialog service should need no code behind.