sckriel
Topic Author
Posts: 6
Joined: 10 Mar 2014, 08:04

Need help with Syntax

10 Mar 2014, 11:05

Good Day,

I am starting work on a GUI using Noesis. I have no experience with XAML or WPF and I'm having some problems with some of the syntax. The tutorials have helped me to understand the basics, but the moment I deviate from them I'm in trouble. I think I mostly know 'what needs to happen', I just don't know the syntax to do it.

1) If I have extended an element (CustomGrid extending Grid, for example) what is the difference between starting the XAML file:
<CustomGrid>
vs.
<Grid x:Class='CustomGrid'>

2) In the examples you extend BaseComponent with functions that can be called via button click:
<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="MainPage1">

    <UserControl.Resources>
        <DataModel2 x:Name="dataModel" SimpleText="hello"/>
    </UserControl.Resources>

    <StackPanel DataContext="{StaticResource dataModel}"
        HorizontalAlignment="Center" VerticalAlignment="Center">
        <TextBlock Text="{Binding SimpleText}" />
        <Button x:Name="btn" Content="Update Text" Click="OnBtnClick" />
    </StackPanel>
</UserControl>
If you where to place this custom UserControl inside another element, how would you change the Button's properties to 'see' the function in MainPage1? It seems to search in Grid (the root element) by default.
<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
	 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	<UserControl x:Class="MainPage1">

		<UserControl.Resources>
			<DataModel2 x:Name="dataModel" SimpleText="hello"/>
		</UserControl.Resources>

		<StackPanel DataContext="{StaticResource dataModel}"
			HorizontalAlignment="Center" VerticalAlignment="Center">
			<TextBlock Text="{Binding SimpleText}" />
			<Button x:Name="btn" Content="Update Text" Click="????????" />
		</StackPanel>
	</UserControl>
</Grid>
3) In several examples you set the DataContext to an element declared as a Static Resource.
<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <UserControl.Resources>
        <DataModel1 x:Name="dataModel" SimpleText="hello"/>
    </UserControl.Resources>

    <StackPanel DataContext="{StaticResource dataModel}"
        HorizontalAlignment="Center" VerticalAlignment="Center">
        <TextBlock Text="{Binding SimpleText}" />
    </StackPanel>
</UserControl>
If a custom UserControl is created with a property and the above example is changed to:
<Grid   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
		xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
	<UserControl
		x:Class='CustomUserControl'>
		
		<StackPanel DataContext="??????"
			HorizontalAlignment="Center" VerticalAlignment="Center">
			<TextBlock Text="{Binding A_Property_In_CustomUserControl}" />
		</StackPanel>
	</UserControl>
</Grid>
How would one change the DataContext definition to locate the correct property?

4) In the tutorials you illustrate commands by binding the command property of a button to a property in a custom class. I would like to know who to use commands without such a binding. The following code works:
<CustomClass 
    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" >
	<CustomClass.CommandBindings>
		<CommandBinding Command="ApplicationCommands.Close"	Executed="Execute" CanExecute="CanExecute" />
	</CustomClass.CommandBindings>

	<StackPanel>
		<Button Command="ApplicationCommands.Close" Content="Do Stuff" />
	</StackPanel>		
</GcsView>
Where Execute and CanExecute are functions defined in CustomClass. However, I can only get this to work by using one of the pre-generated RoutedCommands (ApplicationCommands.Close in this case). How would I go about creating my own RoutedCommands, so that the following code can work:
<CustomClass 
    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" >
	<CustomClass.CommandBindings>
		<CommandBinding Command="MyOwnCommands.DoStuff"	Executed="Execute" CanExecute="CanExecute" />
	</CustomClass.CommandBindings>

	<StackPanel>
		<Button Command="MyOwnCommands.DoStuff" Content="Do Stuff" />
	</StackPanel>		
</GcsView>
Thanks a lot!

Regards,

Steven
 
User avatar
sfernandez
Site Admin
Posts: 1911
Joined: 22 Dec 2011, 19:20

Re: Need help with Syntax

10 Mar 2014, 17:09

Hi,
1) If I have extended an element (CustomGrid extending Grid, for example) what is the difference between starting the XAML file <CustomGrid> vs. <Grid x:Class='CustomGrid'>
x:Class can only be specified on the root element of a XAML as the code-behind class that will implement all the function handlers attached to events. x:Class is invalid on any object that has a parent in the XAML. For example:
// C++
namespace MyNamespace
{
    class MyGrid : public Noesis::Gui::Grid
    {
        // ...
        NS_IMPLEMENT_INLINE_REFLECTION(MyGrid, Noesis::Gui::Grid)
        {
            NsMeta<Noesis::Core::TypeId>("MyNamespace.MyGrid");
        }
    };
}

// Unity
namespace MyNamespace
{
    [Noesis.Extended]
    public class MyGrid: Noesis.Grid
    {
        // ...
    }
}
If this extended class is used as root, you should write the following:
<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="MyNamespace.MyGrid">
</Grid>
When used as a child element you should write the following:
<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:custom="clr-namespace:MyNamespace">
    <custom:MyGrid />
</Grid>
2. In the examples you extend BaseComponent with functions that can be called via button click. If you where to place this custom UserControl inside another element, how would you change the Button's properties to 'see' the function in MainPage1? It seems to search in Grid (the root element) by default.
As explained before, only a root element can specify an x:Class as code-behind class.

The scenario you want to build can be achieved using UserControls (controls that define their contents using an associated xaml and code). For example:
// C++
namespace MyNamespace
{
    class MyUserControl: public Noesis::Gui::UserControl
    {
        // ...
        
        void OnButtonClick(Noesis::Core::BaseComponent* sender,
            const Noesis::Gui::RoutedEventArgs& e)
        {
            // ...
        }
        
        NS_IMPLEMENT_INLINE_REFLECTION(MyUserControl, Noesis::Gui::UserControl)
        {
            NsMeta<Noesis::Core::TypeId>("MyNamespace.MyUserControl");
            
            NsFunc("OnButtonClick", &MyUserControl::OnButtonClick);
            
            NsString source("MyApps/XAML/MyUserControl.xaml");

            Ptr<Noesis::Gui::UIElementData> data = NsMeta<Noesis::Gui::UIElementData>(
                TypeOf<SelfClass>());
            data->OverrideMetadata<NsString>(UserControl::SourceProperty, "Source",
                Noesis::Gui::rameworkPropertyMetadata::Create(source, FrameworkOptions_None));
        }
    }
}
<!-- MyApps/XAML/MyUserControl.xaml -->
<UserControl
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="MyNamespace.MyUserControl">
    <Button Width="200" Height="100" Content="Click Me" Click="OnButtonClick"/>
</UserControl>
Then you can incorporate that user control into other xaml files:
<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:custom="clr-namespace:MyNamespace">
    <custom:MyUserControl HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
3) In several examples you set the DataContext to an element declared as a Static Resource. How would one change the DataContext definition to locate the correct property?
As it occurs in the previous example, you should specify the DataContext in UserControl associated xaml. Although you can set the DataContext when using your user control within other xaml:
<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:custom="clr-namespace:MyNamespace">
    <Grid.Resources>
        <custom:MyData x:Key="MyDataObject"/>
    </Grid.Resources>
    <custom:MyUserControl HorizontalAlignment="Center" VerticalAlignment="Center"
      DataContext="{StaticResource MyDataObject}"/>
</Grid>
4) Where Execute and CanExecute are functions defined in CustomClass. However, I can only get this to work by using one of the pre-generated RoutedCommands (ApplicationCommands.Close in this case). How would I go about creating my own RoutedCommands.
To use your own commands, you have to register the RoutedCommand as follows:
// C++
struct MyOwnCommands
{
    static const Noesis::Gui::RoutedUICommand* DoStuffCommand;
    
    NS_IMPLEMENT_INLINE_REFLECTION(MyOwnCommands, Noesis::Core::NoParent)
    {
        const TypeClass* type = TypeOf<SelfClass>();
        Ptr<Noesis::Gui::CommandData> data = NsMeta<Noesis::Gui::CommandData>(type);
        
        Ptr<Noesis::Gui::KeyGesture> keyGesture = *new Noesis::Gui::KeyGesture(
            Noesis::Gui::Key_F, Noesis::Gui::ModifierKeys_Control);

        DoStuffCommand = data->RegisterCommand(RoutedUICommand::Create("DoStuff",
            "Do some stuff", type, keyGesture.GetPtr()));
    }
};
Hope it helps :)
 
sckriel
Topic Author
Posts: 6
Joined: 10 Mar 2014, 08:04

Re: Need help with Syntax

14 Mar 2014, 13:01

Thank You!

This has really helped me to get on the right track!

Who is online

Users browsing this forum: ivan.fuertes and 1 guest