praeclarum / Ooui

A small cross-platform UI library that brings the simplicity of native UI development to the web
MIT License
1.62k stars 160 forks source link

ViewModel binding via XAML isn't working. #123

Open solatticus opened 6 years ago

solatticus commented 6 years ago

I'm not able to get a view model bound via XAML. If I set it after the InitializeComponent call in the page constructor, it works though.

Checked in an example: https://github.com/solatticus/Ooui.Samples

XamlParseException: Position 8:10. Type sample:ChatSampleViewModel not found in xmlns Ooui.Samples.Forms
Xamarin.Forms.Xaml.CreateValuesVisitor.Visit(ElementNode node, INode parentNode)
Xamarin.Forms.Xaml.ElementNode.Accept(IXamlNodeVisitor visitor, INode parentNode)
Xamarin.Forms.Xaml.RootNode.Accept(IXamlNodeVisitor visitor, INode parentNode)
Xamarin.Forms.Xaml.XamlLoader.Visit(RootNode rootnode, HydrationContext visitorContext)
Xamarin.Forms.Xaml.XamlLoader.Load(object view, string xaml)
Xamarin.Forms.Xaml.Extensions.LoadFromXaml<TXaml>(TXaml view, Type callingType)
Ooui.Samples.Forms.ChatSamplePage.InitializeComponent() in Ooui.Samples.Forms.ChatSamplePage.xaml.g.cs
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Forms.Build.Tasks.XamlG", "0.0.0.0")]
        private global::Xamarin.Forms.ListView MessageListView;

        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Forms.Build.Tasks.XamlG", "0.0.0.0")]
        private void InitializeComponent() {
            global::Xamarin.Forms.Xaml.Extensions.LoadFromXaml(this, typeof(ChatSamplePage));
            UsersListView = global::Xamarin.Forms.NameScopeExtensions.FindByName<global::Xamarin.Forms.ListView>(this, "UsersListView");
            MessageListView = global::Xamarin.Forms.NameScopeExtensions.FindByName<global::Xamarin.Forms.ListView>(this, "MessageListView");
        }
    }
}
Ooui.Samples.Forms.ChatSamplePage..ctor() in ChatSamplePage.xaml.cs
namespace Ooui.Samples.Forms
{
    public partial class ChatSamplePage : ContentPage
    {
       public ChatSamplePage()
        {
            InitializeComponent();
            //BindingContext = new ChatSampleViewModel();
        }
    }
}
Ooui.AspNetCore.SignalR.Controllers.HomeController.SignalRDemo() in HomeController.cs
        {
            return View();
        }
        public ElementResult SignalRDemo()
        {
            var oe = new ChatSamplePage().GetOouiElement();
            var er = new ElementResult(oe, "SignalR Sample");
            return er;
        }
    }
}
lambda_method(Closure , object , object[] )
Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(object target, object[] parameters)
Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor+SyncActionResultExecutor.Execute(ObjectMethodExecutor executor, object controller, object[] arguments)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync()
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync()
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
Microsoft.AspNetCore.Builder.OouiMiddlewareExtensions+<>c__DisplayClass0_0+<<UseOoui>b__0>d.MoveNext()
Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
praeclarum commented 6 years ago

Did you put your ViewModel in a separate DLL? It's possible it hasn't been loaded when Forms goes looking for it.

solatticus commented 6 years ago

It’s all in the same project.

Sent from ProtonMail Mobile

On Fri, Mar 30, 2018 at 4:00 PM, Frank A. Krueger notifications@github.com wrote:

Did you put your ViewModel in a separate DLL? It's possible it hasn't been loaded when Forms goes looking for it.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or mute the thread.

{"api_version":"1.0","publisher":{"api_key":"05dde50f1d1a384dd78767c55493e4bb","name":"GitHub"},"entity":{"external_key":"github/praeclarum/Ooui","title":"praeclarum/Ooui","subtitle":"GitHub repository","main_image_url":"https://cloud.githubusercontent.com/assets/143418/17495839/a5054eac-5d88-11e6-95fc-7290892c7bb5.png","avatar_image_url":"https://cloud.githubusercontent.com/assets/143418/15842166/7c72db34-2c0b-11e6-9aed-b52498112777.png","action":{"name":"Open in GitHub","url":"https://github.com/praeclarum/Ooui"}},"updates":{"snippets":[{"icon":"PERSON","message":"@praeclarum in #123: Did you put your ViewModel in a separate DLL? It's possible it hasn't been loaded when Forms goes looking for it."}],"action":{"name":"View Issue","url":"https://github.com/praeclarum/Ooui/issues/123#issuecomment-377609375"}}}

praeclarum commented 6 years ago

OK, cool. Can you also paste in some of the XAML where you declare the namespace and create the binding? I've never done the binding in XAML.

solatticus commented 6 years ago

It’s in the link I posted, but I can copy it over when I get home.

Thanks for this!

Sent from ProtonMail Mobile

On Fri, Mar 30, 2018 at 4:05 PM, Frank A. Krueger notifications@github.com wrote:

OK, cool. Can you also paste in some of the XAML where you declare the namespace and create the binding? I've never done the binding in XAML.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or mute the thread.

{"api_version":"1.0","publisher":{"api_key":"05dde50f1d1a384dd78767c55493e4bb","name":"GitHub"},"entity":{"external_key":"github/praeclarum/Ooui","title":"praeclarum/Ooui","subtitle":"GitHub repository","main_image_url":"https://cloud.githubusercontent.com/assets/143418/17495839/a5054eac-5d88-11e6-95fc-7290892c7bb5.png","avatar_image_url":"https://cloud.githubusercontent.com/assets/143418/15842166/7c72db34-2c0b-11e6-9aed-b52498112777.png","action":{"name":"Open in GitHub","url":"https://github.com/praeclarum/Ooui"}},"updates":{"snippets":[{"icon":"PERSON","message":"@praeclarum in #123: OK, cool. Can you also paste in some of the XAML where you declare the namespace and create the binding? I've never done the binding in XAML."}],"action":{"name":"View Issue","url":"https://github.com/praeclarum/Ooui/issues/123#issuecomment-377610572"}}}

praeclarum commented 6 years ago

Sorry, missed the link, it's perfect.

zbigniew-gajewski commented 6 years ago

In my case (WASM + Xamarin Forms) MVVM works as expected (Button.Command, Button.Text). Example here: https://github.com/zbigniew-gajewski/ooui-wasm-aspnet-core-xaml

solatticus commented 6 years ago

Does declaring & binding the ViewModel via XAML work?

zbigniew-gajewski commented 6 years ago

Yes! (at least Button.Command, Button.Text). Here is working example (based on Ooui.Wasm) with declarative binding XAML / ViewModel: https://github.com/zbigniew-gajewski/ooui-wasm-aspnet-core-xaml

MarkStega commented 6 years ago

I have also had success binding to the viewmodel directly from XAML:

<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:infrastructureMVVMFrameworkConverters="clr-namespace:OouiWXF.Infrastructure.MVVMFramework.Converters" xmlns:local="clr-namespace:OouiWXF" xmlns:viewModel="clr-namespace:OouiWXF.ViewModels.MainPage" x:Class="OouiWXF.MainPage">

`

</ContentPage.BindingContext>`

<Label x:Name="StartNarrative" Text="{Binding pStartNarrative, Mode=TwoWay}" />

and then in MainPage.cs class definition:

static public MainPageViewModel pMainPageViewModel;

and in the constructor:

pMainPageViewModel = (MainPageViewModel)this.BindingContext;

MarkStega commented 6 years ago

Here is a repository with the complete code: https://bitbucket.org/MarkStegaOHI/oouiwxf/src/develop/

Thanks to @zbigniew-gajewski for the dll & wasm types in the web server project; I've been meaning to get to this for a while.