教程12:扩展NoesisGUI
扩展NoesisGUI
基于XAML的noesisGUI是一个可以以多种方式扩展的框架。例如,您可以创建自己的Converters,Commands,CustomControls,UserControls或代码隐藏类。本教程重点介绍使用您自己的类扩展noesisGUI所必须执行的步骤。显然,步骤因要使用的语言而异。
我们要做的第一件事是编写一个非常简单的XAML,它带有一个TextBox,您可以在其中编写文本,以及一个TextBlock,它通过转换器过滤输出您编写的文本。我们将要实现的转换器将输入转换为大写。
<Grid
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Sample">
<Grid.Resources>
<local:UppercaseConverter x:Key="Converter"/>
</Grid.Resources>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Background="Blue">
<TextBox x:Name="Input" Width="100"/>
<TextBlock Text="{Binding Text, ElementName=Input, Converter={StaticResource Converter}}"
Margin="5"/>
</StackPanel>
</Grid>
突出显示的行表示正在使用扩展类(在本例中为名称空间Sample下)。如果按原样使用此XAML,我们将收到一条警告,指示未知的Sample.UppercaseConverter类型。我们需要实现一个使用该名称注册的新类。让我们看看如何做到这一点。
用C ++扩展
#include <NsCore/Noesis.h>
#include <NsCore/TypeOf.h>
#include <NsCore/RegisterComponent.h>
#include <NsCore/ReflectionImplement.h>
#include <NsGui/BaseValueConverter.h>
using namespace Noesis;
namespace Sample
{
////////////////////////////////////////////////////////////////////////////////////////////////////
class UppercaseConverter final: public BaseValueConverter
{
public:
bool TryConvert(BaseComponent* value, const Type* targetType, BaseComponent* /*parameter*/,
Ptr<BaseComponent>& result) override
{
if (targetType == TypeOf<NsString>() && Boxing::CanUnbox<NsString>(value))
{
NsString text = Boxing::Unbox<NsString>(value);
text.make_upper();
result = Boxing::Box<NsString>(text);
return true;
}
return false;
}
private:
NS_IMPLEMENT_INLINE_REFLECTION(UppercaseConverter, BaseValueConverter)
{
NsMeta<TypeId>("Sample.UppercaseConverter");
}
};
}
上面显示的代码说明了实现新类所需的关键点:
- 新类必须始终从其相应的基类派生。在这种情况下,基类是BaseValueConverter,因为我们对IValueConverter接口感兴趣。
- 新类必须实现所需的方法。BaseValueConverter要求我们实现TryConvert和TryConvertBack,但是在此特定示例中,仅在一个方向上进行转换,我们仅需要实现TryConvert。它是通过将文本取消装箱,转换为大写字母并返回装箱的对象来实现的。
- 最后,反射标记必须添加到我们的新类中:
NS_IMPLEMENT_INLINE_REFLECTION(UppercaseConverter, BaseValueConverter)
{
NsMeta<TypeId>("Sample.UppercaseConverter");
}
在这里,我们表明我们的类UppercaseConverter 继承自BaseValueConverter,并在名称空间“ Sample”下以名称“ UppercaseConverter”注册。这是XAML将用来引用此本机类的标识符。在正常情况下,此标识符是类的名称。
在XAML中使用此类之前,必须在组件工厂中注册它。必须在Noesis初始化之后并且在加载相应的XAML之前完成此操作。我们的应用程序框架提供了可用于此目的的虚拟功能:
class AppLauncher final: public ApplicationLauncher
{
private:
void RegisterComponents() const override
{
NsRegisterComponent<Sample::UppercaseConverter>();
}
}
正确注册该类之后,XAML将会正确加载,并且将相应地使用我们的转换器。
ExtendingTutorialImg1.jpg用C#扩展
在C#中,一切都变得更容易,因为注册是在内部自动完成的,并且我们不需要应用反射宏,因为已经支持开箱即用的反射。您只需要在名称空间Sample下创建类UppercaseConverter并实现IValueConverter接口。
using System;
using System.Globalization;
using Noesis;
namespace Sample
{
public class UppercaseConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((string)value).ToUpper();
}
public object ConvertBack(object value, Type targetType, object parameter,
CultureInfo culture)
{
return null;
}
}
}