Page 1 of 1

Instantiate ViewModels

Posted: 13 Dec 2024, 11:28
by MarioBarbero
I was seeing this sample in your git (https://github.com/Noesis/Tutorials/tre ... ttons/C%23) and I have seen that You instantiate the datacontext in code behind instead instantiate in xaml file and active IntelliCode for properties in ViewModel. Why do you instantiate ViewModel in code behind instead xaml file, it is because instantiate datacontext in xaml file doesnt work with Noesis?

I attach the code (your way and my way). The code of ViewModel is the same both cases

-------------------- YOUR EXAMPLE --------------------
namespace TestNoesis
{
    /// <summary>
    /// Lógica de interacción para TestNoesisWindow.xaml
    /// </summary>
    public partial class TestNoesisWindow : Window
    {
        public TestNoesisWindow()
        {
            System.WeakReference wr = new System.WeakReference(this);
            this.Initialized += (s, e) => { ((TestNoesisWindow)wr.Target).OnInitialized(s, e); };
            this.InitializeComponent();
        }

#if NOESIS
        private void InitializeComponent()
        {
            Noesis.GUI.LoadComponent(this, "/TestNoesis;component/TestNoesisWindow.xaml");
        }
#endif

        private void OnInitialized(object sender, EventArgs args)
        {
            this.DataContext = new TestNoesisWindowViewModel();
        }
    }
}
<Window x:Class="TestNoesis.TestNoesisWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
        xmlns:local="clr-namespace:TestNoesis"
        xmlns:noesis="clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions"
        mc:Ignorable="d"
        Title="TestNoesisWindow" Height="450" Width="800">


    <Window.Resources>
        <Storyboard x:Key="Intro">
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="StartButton">
                <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="1">
                    <EasingDoubleKeyFrame.EasingFunction>
                        <BackEase EasingMode="EaseOut" Amplitude="0.5"/>
                    </EasingDoubleKeyFrame.EasingFunction>
                </EasingDoubleKeyFrame>
            </DoubleAnimationUsingKeyFrames>
-------------------- MY EXAMPLE --------------------
namespace TestNoesis
{
    /// <summary>
    /// Lógica de interacción para TestNoesisWindow.xaml
    /// </summary>
    public partial class TestNoesisWindow : Window
    {
        public TestNoesisWindow()
        {
            this.InitializeComponent();
        }

#if NOESIS
        private void InitializeComponent()
        {
            Noesis.GUI.LoadComponent(this, "/TestNoesis;component/TestNoesisWindow.xaml");
        }
#endif
    }
}
<Window x:Class="TestNoesis.TestNoesisWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
        xmlns:local="clr-namespace:TestNoesis"
        xmlns:noesis="clr-namespace:NoesisGUIExtensions;assembly=Noesis.GUI.Extensions"
        mc:Ignorable="d"
        Title="TestNoesisWindow" Height="450" Width="800">

    <Window.DataContext>
        <local:TestNoesisWindowViewModel/>
    </Window.DataContext>

    <Window.Resources>
        <Storyboard x:Key="Intro">
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="StartButton">
                <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="1">
                    <EasingDoubleKeyFrame.EasingFunction>
                        <BackEase EasingMode="EaseOut" Amplitude="0.5"/>
                    </EasingDoubleKeyFrame.EasingFunction>
                </EasingDoubleKeyFrame>
            </DoubleAnimationUsingKeyFrames>

Re: Instantiate ViewModels

Posted: 13 Dec 2024, 13:28
by sfernandez
Usually you don't want to tie a View (the XAML) with a particular ViewModel instance, because that way you can share the same view with different data, for example:
<StackPanel>
  <Border DataContext="{Binding PlayerA}">
    <local:PlayerView/>
  </Border>
  <Border DataContext="{Binding PlayerB}">
    <local:PlayerView/>
  </Border>
</StackPanel>
Assigning it in the code-behind is just for testing purposes, as a way to indicate that the DataContext is coming from another source (probably inherited or set in an outer XAML).

Re: Instantiate ViewModels

Posted: 13 Dec 2024, 14:36
by MarioBarbero
I dont understand. The PlayerA and PlayerB properties should be defined in the ViewModel of the current xaml file, right?
And PlayerView xaml file must be have its ViewModel called, for example, PlayerViewViewModel.

Re: Instantiate ViewModels

Posted: 13 Dec 2024, 17:23
by sfernandez
If you instantiate the ViewModel in the View (XAML), then only 1 instance with specific values can be used in that View. Besides, the game/app logic won't be able to provide the data for the View, limiting its use.

In my example the game will define a PlayerViewModel (containing the properties of the player), then there would be another MainViewModel which would expose the 2 players (2 PlayerViewModel properties, each one returning a different instance with their own values). The game could update the player stats and info without the View having to know that, the View will just receive the property change notifications to update the UI.

I hope this helps.

Re: Instantiate ViewModels

Posted: 13 Dec 2024, 19:25
by MarioBarbero
I understand. You are right, my way is not valid in this case.

Thank you