این مقاله ویژگی های زبان XAML را توضیح و نشان می دهد چگونه می توان از آن برای نوشتن برنامه های Windows Presentation Foundation یا (WPF) استفاده کرد.
XAML چیست؟
XAML، یک زبان نشانه دار تعریفی (declarative markup language) است. این زبان، همانگونه که به مدل برنامه نویسی .NET Framework اعمال شده است، ایجاد user interface برای برنامه .NET Framework را ساده می کند. می توان عنصرهای UI قابل رویتی در مارک آپ تعریفی XAML ایجاد کرد، و سپس با استفاده از فایل های پشت کد، که از طریق تعاریف کلاس جزیی به مارک آپ ملحق شده اند، تعریف UI را از منطق زمان اجرا جدا کرد. این زبان بطور مستقیم فرایند ایجاد اشیا در مجموعه ای معین از تایپ های پشتیبان تعریف شده در اسمبلی ها ارائه می کند. این کار برعکس اکثر زبان های مارک آپ است، که معمولاً زبانی تعبیر شده و بدون چنین رابطه مستقیمی با سیستم تایپ پشتیبان هستند. XAML، یک جریان کاری (workflow) را که بخش های مستقل می توانند روی UI ومنطق برنامه، با استفاده از ابزارهای مختلف کار می کنند، فعال می کند.
فایل های XAML، وقتی بصورت متن ارائه می شوند، فایل هایی هستند که معمولاً دارای اکتنشن .xaml هستند. این فایل ها را می توان توسط هر انکدینگ XAMLیی کدگذاری (encode) کرد. اما انکدینگ UTF-8 رایج ترین است.
مثال زیر چگونگی ایجاد یک دکمه بعنوان یک UI را نشان می دهد. هدف این مثال تنها این است که نشان دهد XAML چگونه استعاره های (metaphor) رایج برنامه نویسی UI را نمایش می دهد.
<StackPanel>
<Button Content="Click Me"/>
</StackPanel>
خلاصه ای از سینتکس XAML
ابن بخش، فرم های پایه ای سینتکس XAML را توضیح می دهد، و مثالی کوتاه از markup می آورد. هدف این بخش، در اختیار گذاشتن اطلاعات کاملی در مورد هر فرم سینتکس، از قبیل چگونگی نمایش این فرم ها در سیستم تایپ پشتیبان نیست.
اگر شما آشنایی قبلی با XAML داشته باشید، اغلب موضوعات بخش های بعدی، برای شما مبتدی خواهد بود. این موضوع نتیجه یکی از اصول اولیه طراحی XAML است. این زبان مفاهیم خودش را تعریف می کند، اما این مفاهیم در زبان XAML و فرم مارک آپ کارایی دارند.
عنصرهای شی
معمولاً عنصر شی نمونه ای (instanceS) از یک type را تعریف می کند. این type در اسمبلی هایی که تایپ های پشتیبان را برای تکنولوژی ای که از XAML بعنوان زبان استفاده می کنند، تعریف می شود.
سینتکس عنصر شی همیشه با علامت < شروع می شود. و به دنبالش نام تایپی می آید که می خواهید در یک نمونه (instance) ایجاد کنید (این نام می تواند حاوی یک پیشوند باشد، پیشوند مفهومی است که بعداً توضیح داده خواهد شد). بعد از این، می توانید بصورت اختیاری اتریبیوت هایی در مورد عنصر شی تعریف کنید. برای تکمیل تگ عنصر شی، در آخرش علامت > بگذارید. در عوض می توانید از یک فرم که خودش بسته می شود و دارای هیچ محتوایی نیست استفاده کنید و این کار را می توانید باوسیله تگی با forward slash و علامت /> در ادامه اش انجام دهید. مثلاً نگاهی دوباره به مارک آپ مثال قبلی بیاندازید.
این مثال دو عنصر شی را معین می کند: <StackPanel> ( با content، و سپس تگ انتهایی)؛ و <Button .../>
( فرمی که خودش بسته می شود، با چندین اتریبیوت). عنصرهای شی StackPanel و Button هر کدام با نام کلاسی که توسط WPF و بخشی از اسمبلی های WPF تعریف شده اند، مساوی می شوند. وقتی یک تگ عنصر شی تعیین می کنید، در واقع دستورالعملی برای پردازش XAML ایجاد می کنید تا نمونه ای جدید ایجاد کنید. هر نمونه توسط فراخوانی constructor پیش فرض، هنگام parse یا load کردن تایپ اصلی ایجاد می شود.
سینتکس اتریبیوت (پراپرتی ها)
پراپرتی های شی را می توان بصورت اتریبیوت های عنصر شی تعریف کرد. اتریبیوت سینتکس، پراپرتی ای را که در اتریبیوت سینتکس، که متعاقبش علامت = می آید، تنظیم شده است، نامگذاری می کند. مقدار اتریبیوت همیشه بصورت رشته ای تعیین می شود که حاوی علامت نقل قول "" هست.
اتریبیوت سینتکس، موثرترین سینتکس تنظیمات پراپرتی است و بهترین سینتکس برای استفاده برنامه نویسانی است که در گذشته از زبان های مارک آپ استفاده کرده اند. مثلاً مارک آپ زیر دکمه ای ایجاد می کند که دارای متن قرمز و پیش زمینه آبی است که متنی که بصورت Content تعیین شده را نیز نمایش می دهد.
<Button Background="Blue" Foreground="Red" Content="This is a button"/>
سینتکس عنصر پراپرتی (Property Element Syntax)
اتریبیوت سینتکس برای بعضی از پراپرتی های عنصر شی قابل اعمال نیست، زیرا شی یا اطلاعات لازم برای در اختیار گذاشتن مقدار (value) را نمی توان درون علامت نقل قول و محدودیت های رشته سینتکس اتریبیوت بیان کرد. در چنین مواردی، می توان از سینتکسی که property element syntax شناخته م شود استفاده کرد.
سینتکس تگ شروع عنصر پراپرتی (property element start) عبارت است از: <typeName.propertyName>. معمولاً محتوای این تگ عنصر شی تایپی هست که پراپرتی بعنوان مقدار (value) درنظر می گیرد. بعد از تعیین محتوا، باید عنصر پراپرتی را با یک end tag تمام کنید. سینتکس end tag، عبارت است از: </typeName.propertyName>.
اگر اتریبیوت سینتکس قابل اعمال باشد، معمولا، استفاده از آن راحت تر است و مارک آپ های فشرده تر را ساپورت می کند. مثال زیر، همان پراپرتی هایی را نشان می دهد که در مثال اتریبیوت سینتکس قبلی تنظیم شده اند، اما این بار با استفاده از property element syntax پراپرتی Button تنظیم شده اند.
<Button>
<Button.Background>
<SolidColorBrush Color="Blue"/>
</Button.Background>
<Button.Foreground>
<SolidColorBrush Color="Red"/>
</Button.Foreground>
<Button.Content>
This is a button
</Button.Content>
</Button>
سینتکس Collection
زبان XAML حاوی بهینه سازی هایی است که مارک آپ های قابل خواندنی تری تولید می کنند. یکی از این بهینه سازی ها این است که اگر پراپرتی مشخصی، تایپ کالکشنی را بگیرد، آنگاه آیتم هایی که در مارک آپ بصورت عنصرهای child در مقدار آن پراپرتی تعریف می شوند، بخشی از آن کالکشن می شوند. در این مورد، کالکشن عنصر شی child، مقداری است که در پراپرتی کالکشن تنظیم می شود.
مثال زیر، سینتکس کالکشن تنظیم مقادیر پراپرتی GradientStops را نشان میدهند:
<LinearGradientBrush>
<LinearGradientBrush.GradientStops>
<!-- no explicit new GradientStopCollection, parser knows how to find or create -->
<GradientStop Offset="0.0" Color="Red" />
<GradientStop Offset="1.0" Color="Blue" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
پراپرتی های XAML Content
XAML، ویژگی زبانی را تعریف می کند که یک کلاس توسط آن می تواند یکی از پراپرتی هایش را به پراپرتی XAML content تخصیص دهد. عنصرهای child آن عنصر شی، جهت تنظیم مقدار آن پراپرتی content، مورد استفاده قرار می گیرد. بعبارت دیگر، برای پراپرتی content می توانید هنگان تنظیم آن پراپرتی در مارک آپ XAML، یک عنصر پراپرتی را حذف کنید و یک استعاره parent/child در مارک آپ تولید کنید.
مثلاً، Border، پراپرتی کانتنت Child را تعیین می کند. با دو عنصر Border زیر بطور یکسان رفتار می شود. اولی از مزایای content property syntax بهره می برد و عنصر پراپرتی Border.Child را حذف می کند. دومی Border.Child را بدون واسطه نشان می دهد.
<Border>
<TextBox Width="300"/>
</Border>
<!--explicit equivalent-->
<Border>
<Border.Child>
<TextBox Width="300"/>
</Border.Child>
</Border>
مقدار XAML content property، بعنوان قانونی در زبان XAML، باید یا کلاً قبل یا کلاً بعد از هر عنصر پراپرتی دیگری روی همان عنصر شی داده شود. مثلاً مارک آپ زیر compile نمی شود:
<Button>I am a
<Button.Background>Blue</Button.Background>
blue button</Button>
محتوی متنی (Text Content)
تعداد کمی از عناصر XAML می توانند بطور مستقیم متن را درون محتوایشان پردازش کنند. بمنظور فعال سازی این کار، یکی از موارد زیر باید true باشد:
- کلاس باید یک content property تعریف کند، و آن content property باید تایپی قابل تخصیص به رشته (string) باشد (این تایپ می تواند Object باشد). مثلاً، هر ContentControl از Content بعنوان content property و تایپ Objectاش استفاد می کند.
- تایپ باید یک تبدیل کننده تایپ تعریف کند، که در این مورد، از محتوای متنی بعنوان متن آغازی برای آن تبدیل کننده تایپ استفاده می شود. مثلاً <Brush>Blue</Brush>. این کلاس عملاً کمتر رایج است.
- تایپ باید یک primitive شناخته شده زبان XAML باشد.
Content Properties و Collection Syntax ترکیب شده
مثال زیر را در نظر بگیرید:
<StackPanel>
<Button>First Button</Button>
<Button>Second Button</Button>
</StackPanel>
در اینجا، هر Button، عنصر child در StackPanel است. این مارک آپی موثر است که دو تگ زیر را به دو دلیل متفاوت حذف می کند.
Omitted StackPanel.Children property element: StackPanel از Panel مشتق می شود. Panel، Panel.Children را بعنوان پراپرتی XAML contentاش تعریف می کند.
: Omitted UIElementCollection object element پراپرتی Panel.Children، تایپ UIElementCollection را می گیرد که را پیاده سازی می کند. بر اساس قوانین XAML، تگ عنصر کالکشن را می توان برای پردازش کالکشن هایی از قبیل IList حذف کرد. (در این مورد، UIElementCollection عملاً نمی توان instantiate کرد زیرا constructor پیش فرض را expose نمی کند. بهمین دلیل است که عنصر شی UIElementCollection بصورت commented out نشان داده می شود.
<StackPanel>
<StackPanel.Children>
<!--<UIElementCollection>-->
<Button>First Button</Button>
<Button>Second Button</Button>
<!--</UIElementCollection>-->
</StackPanel.Children>
</StackPanel>
سینتکس اتریبیوت (رویدادها (Events))
سینتکس اتریبیوت را می توان برای اعضایی که رویداد (event)محسوب می شوند و نه پراپرتی، نیز استفاده کرد. در این مورد، نام اتریبیوت همان نام رویداد است. در پیاده سازی WPF از رویدادهای XAML، مقدار اتریبیوت، نام یک handler است که delegate رویداد را پیاده سازی می کند. مثلاً، مارک آپ زیر، یک هندلر برای رویداد Click به یک Button مه در مارک آپ ایجاد شده، تخصیص می دهد.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ExampleNamespace.ExamplePage">
<Button Click="Button_Click" >Click Me!</Button>
</Page>
مطالب بیشتری در مورد eventها و XAML در WPF وجود دارد. مثلاً شاید فکر کنید آنچه که ClickHandler در اینجا reference می کند، چگونه نمایش داده و تعریف می شود. این موضوع در بخش های بعدی مقاله مورد بحث قرار خواهد گرفت.
Case و Whitespace در XAML
XAML، معمولاً به حروف بزرگ و گوچک حساس است. است. بمنظور resolve کردن تایپ های پشتیبان، همان قوانینی که CLR را بحروف بزرگ و کوچک حساس می کنند، WPF XAML را نیز حساس می کنند. عنصرهای شی، عنصرهای پراپرتی، و نام های اتریبیوت همگی باید با استفاده از sensitive casing،هنگام مقایسه براساس نام با تایپ اصلی در اسمبلی، یا با عضوی از یک تایپ، تعیین شوند. کلیدواژه ها و primitiveهای زبان XAML نیز به حروف کوچک و بزرگ حساس هستند valueها همیشه حساس نیستند. حساسیت در valueها، بستگی به رفتار تبدیل کننده تایپ دارد که با پراپرتی ای که value آنرا می گیرد در ارتباط است. بعنوان مثال، پراپرتی هایی که تایپ Boolean را می گیرند، می توانند مقادیر معادل true یا false را بگیرند، فقط به این دلیل که پارسر WPF برای XAML مبدل نوع داده ای رشته ای به Boolean، قبلاً اینها را بصورت معادل هایی مجاز کرده است.
پردازشگرها و serialize کننده های WPF XAML کل فضای خالی های غیر مهم را نادیده می گیرند، و هر فضای خالی مهم را نرمال می کنند. این، با رفتار پیش فرض XAML در برخورد با فضاهای خالی سازگار است. این رفتار معمولاً فقط هنگامی که رشته ها را درون پراپرتی content تعیین می کنیم، اهمیت و تاثیر دارد. به عبارتی ساده تر، XAML، فضا، linefeed، و کارکترهای تب را به فضاها تبدیل می کند، و سپس در صورتی که در انتهای هر رشته مجاور به هم فضایی پیدا کند، آنرا حفظ می کند.
اکتنش های مارک آپ
اکتنشن های مارک آپ، مفهومی در زبان XAML هستند. وقتی برای در اختیار گذاشتن مقدار سینتکس اتریبیوت بکار می رود، علامت های { و }، استفاده از اکتنشن مارک آپ را نشان می دهند. این کاربرد، پردازش XAML را به گریز از برخورد معمولی مقادیر اتریبیوت، چه بصورت رشته ای دارای حروف و چه بصورت مقداری قابل تبدیل، هدایت می کند.
رایج ترین اکتنشن های مارک آپ که در برنامه نویسی WPF مورد استفاده قرار می گیرد، Binding است، که برای عبارات data bining، و resource referenceهای StaticResource و DynamicResource بکار می روند. با استفاده از اکستنشن های مارک آپ می توان از سینتکس اتریبیوت برای فراهم کردن value برای تهیه مقادیر پراپرتی استفاده کرد، حتی اگر آن پراپرتی بطور کلی attribute syntax ساپورت نکند. اکستنشن های مارک آپ اغلب از تایپ های عبارت متوسط برای فعال کردن ویژگی هایی از قبیل به تاخیر انداختن مقادیر یا reference کردن اشیای دیگر که فقط هنگان اجرا حاضر هستند، استفاده می کنند.
مثلاً، مارک آپ زیر مقدار پراپرتی Style را با استفده از attribute syntax تنظیم می کند. این پراپرتی، نمونه ای از کلاس Style را می گیرد، که بطور پیش فرض نمی تواند با یک رشته سینتکس اتریبیوت، instantiate شود. اما در این مورد، اتریبیوت، اکتنشن مارک آپ مشخصی، یعنی StaticResource را reference می کند. وقتی آن اکتنشن مارک آپ پردازش می شود، ریفرنسی را به استایلی که قبلاً بصورت منبعی key شده در منبع لغت نامه instantiate شده را باز می گرداند.
<Page.Resources>
<SolidColorBrush x:Key="MyBrush" Color="Gold"/>
<Style TargetType="Border" x:Key="PageBackground">
<Setter Property="Background" Value="Blue"/>
</Style>
...
</Page.Resources>
<StackPanel>
<Border Style="{StaticResource PageBackground}">
...
</Border>
</StackPanel>
تبدیل کننده های تایپ (Type Converters)
در بخش قبلی گفته شد که مقدار اتریبیوت باید بتواند توسط یک رشته تنظیم شود. مدیریت پایه ای چگونگی تبدیل رشته ها به دیگر تایپ های شی یا مقادیر ابتدایی، بر پایه خود تایپ String است، بعلاوه پردازش ذاتی بعضی از تایپ ها از قبیل DateTime یا Uri. اما خیلی از تایپ ها یا اعضای WPF این تایپ ها، رفتار پردازش اتریبیوت رشته را توسعه می دهند، بطوری که نمون هایی از تایپ های شی پیچیده تر را می توان بصورت رشته یا اتریبیوت تعیین کرد.
ساختار Thickness، مثالی از تایپی است که دارای مبدل تایپ است که برای صفحات XAML فعال شده است. Thickness، اندازه گیری های درون یک مستطیل nest شده را نمایش می دهد و بعنوان مقدار برای پراپرتی هایی از قبیل Margin بکار می رود. با قرار دادن مبدل تایپ روی Thickness، همه پراپرتی هایی که از یک Thickness استفاده می کنند، راحت تر تعیین می شوند، زیرا می توان آنها را بصورت اتریبیوت تعیین کرد. مثال زیر، از مبدل تایپ و سینتکس اتریبیوت برای تهیه مقدار برای Margin استفاده میکند:
<Button Margin="10,20,10,30" Content="Click me"/>
مثال attribute syntax قبلی، معادل مثال سینتکس طولانی زیر است، ولی در عوض، Margin از طریق سینتکس عنصر پراپرتی تنظیم می شود که حاوی عنصر شی Thickness است. پراپرتی های چهار دکمه Thickness، روی نمونه جدید بصورت اتریبیوت تنظیم می شوند:
<Button Content="Click me">
<Button.Margin>
<Thickness Left="10" Top="20" Right="10" Bottom="30"/>
</Button.Margin>
</Button>
|
نکته:
همچنین تعداد محدودی شی وجود دارد که تبدیل تایپ تنها راه رایج برای تنظیم پراپرتی به آن تایپ بدون درگیر کردن یک زیر کلاس است، زیرا خود تایپ دارای constructor پیش فرض نیست. Cursor، مثالی از این دست است.
|
عنصرهای ریشه XAML و فضاهای نامی XAML
برای اینکه یک فایل XAML هم دارای شکل خوب باشد و هم فایلی معتبر باشد، فقط یک عنصر باید داشته باشد. در سناریوهای معمولی WPF، از یک فایل ریشه ای استفاده می شود که معنی برجسته ای در مدل برنامه WPF باشد ( مثلاً Windows یا Page برای صفحه، ResourceDictionary برای دیکشنری خارجی، یا Application برای تعریف برنامه). مثال زیر، عنصر ریشه فایل معمولی XAML برای صفحه WPF را با عنصر ریشه Page نشان می دهد.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
...
</Page>
همچنین عنصر ریشه حاوی اتریبیوت های xmlns و xmlns:x. است. این اتریبیوت ها به پردازشگر XAML نشان می دهد کدام فضاهای نامی XAML حاوی تعاریف تایپ برای تایپ های پشتیبانی هستند که مارک آپ آنها را بصورت عنصر ریفرنس می کند. اتریبیوت xmlns بطور معین فضای نامی پیش فرض XAML رانشان می دهد. درون فضای نامی XAML، می توان عناصر شی در مارک آپ را بدون پیشوند تعیین کرد. در اکثر سناریوهای برنامه WPF، و تقریباً همه مثال ها ارائه شده در بخش های دبلیو پی اف SDK، فضای نامی پیش فرض XAML به فضای نامی http://schemas.microsoft.com/winfx/2006/xaml/presentation، مپ (map) می شود. اتریبیوت xmlns:x، فضای نامی اضافی ای نشان می دهد که فضای نامی زبان XAML زیر را مپ می کند:
http://schemas.microsoft.com/winfx/2006/xaml
استفاده از xmlns برای تعریف اسکوپ برای استفاده و مپینگ فضای نامی، با XML 1.0 specification سازگار است. تفاوت اسکوپ های نامی XAML با اسکوپ های نامی XML در این است که اسکوپ نامی XAML در مورد اینکه چگونه عنصرهای اسکوپ نامی توسط تایپ ها هنگامی که به type resolution و پارسینگ XAML می رسد، چیز جدیدی استدلال می کند.
توجه کنید که اتریبیوت های xmlns فقط برای عنصر ریشه هر فایل XAML ضروری هستند. تعاریف xmlns به تمامی عنصرهای نزولی (descendant) عنصر ریشه اعمال می شوند (این رفتار نیز با XML 1.0 specification برای xmlns سازگار است). این اتریبیوت ها در عنصرهای دیگر زیرریشه نیز مجاز هستند، و به هر عنصر نزولی عنصر تعریف کننده اعمال می شوند. اما تعریف یا بازتعریف عادی فضاهای نامی XAML ممکن است به استایل مارک آپ XAML، که خواندنش مشکل است، منجر شود.
پیاده سازی WPF از پردازشگر XAMLاش حاوی زیربنایی است که از اسمبلی های هسته ای WPF آگاه است. اسمبلی های هسته ای WPF، برای بعضی از تایپ هایی که مپینگ های WPF به فضای نامی پیش فرض XAML را ساپورت می کنند، شناخته شده هستند. این کار از طریق پیکربندی ای که بخشی از فایل ساخت پروژه تان و ساخت WPF و سیستم های پروژه تان است انجام می شود. بنابراین، تعریف فضای نامی پیش فرض XAML مانند xmlns پیش فرض، تنها چیزی است برای ریفرنس کردن عنصرهایی که از اسمبلی های WPF می آیند نیاز دارید.
پیشوند x:
در مثال قبلی از عنصر ریشه، از پیشوند x: برای مپ کردن فضای نامی http://schemas.microsoft.com/winfx/2006/xaml استفاده شد، که فضای نامی اختصاصی XAML است که constructهای زبان XAML را ساپورت می کند. از این پیشوند برای مپ کردن فضای نامی XAML در templateهای پروژه ها، مثال ها، و مستند سازی (documentation) در سراسر این SDK استفاده می شود. فضای نامی XAML برای زبان XAML حاوی چندین construct برنامه نویسی است که کاربرد زیادی دارد. در زیر لیستی از رایج ترین constructهای برنامه نویسی با پیشوند x: آورده شده است:
x:Key: کلیدی مخصوص برای هر ریسورس در ResourceDictionary (یا هرمفهوم دیکشنری شبیه در frameworkهای دیگر) ایجاد می کند. احتمالاً این کلید %90 استفاده از x: را که در مارک آپ برنامه های WPF می بینید به خود اختصاص می دهد.
x:Class: فضای نامی CLR و نام کلاس را برای کلاسی که کد پشتی (code-behind) را برای صفحه در اختیار می گذارد، تعیین می کند. شما باید چنین کلاسی برای ساپورت کد پشتی برای هر مدل برنامه نویسی WPF داشته باشید، و بنابراین همیشه x: را باید بصورت مپ شده ببینید، حتی اگر هیچ ریسورسی وجود نداشته باشد.
x:Name: نام شی زمان اجرا را برای مثالی که در کد زمان اجرا، بعد از اینکه شی عنصر پردازش شد، وجود دارد تعیین می کند. بطور کلی باید از پراپرتی معادل که در WPF برای x:Name: تعریف شده است استفاده کنید. چنین پراپرتی هایی به پراپرتی پشتیبان CLR مپ می شوند و در نتیجه برای برنامه نویسی مناسب تر هستند، که شما در آن معمولاً از کد زمان اجرا استفاده می کنید تا عنصرهای نام دار را از XAML آغاز شده پیدا کند. رایج تین پراپرتی از این دست، FrameworkElement.Name است. ممکن است هنگامی که پراپرتی Name در یک تایپ ویژه ساپورت نمی شود، هنوز از x:Name استفاده کنید. این کار در بعضی از سناریوهای انیمیشن اتفاق می افتد.
x:Static: ریفرنسی را فعال می کند که یک valueی ایستاتیک را که پراپرتی سازگار با XAML نیست را بازمی گرداند.
x:Type: ریفرنسی را بر اساس نام تایپ می سازد. از این برای تعیین اتریبیوت هایی که type را می گیرند استفاده می شود، از قبیل Style.TargetType، گرچه این پراپرتی اغلب دارای تبدیل string به Type است بطوریکه استفاده از اکستنشن مارک آپ x:Type اختیاری است.
constructهای برنامه نویسی دیگری هم در فضای نامی x: prefix/XAML وجود دارند که خیلی رایج نیستند.
پیشوندها و تایپ های سفارشی
برای اسمبلی های سفارشی خودتان، یا اسمبلی هایی خارج از هسته PresentationCore، PresentationFramework، و WindowsBase در WPF، می توانید اسمبلی را بعنوان مپینگ سفارشی xmlns تعیین کرد. سپس می توانید تا وقتی که آن تایپ بطور صحیح برای ساپورت کاربردهای XAML پیاده سازی می شموند، تایپ هایی را از اسمبل ای که خودتان وجود دارد، ریفرنس کنید.
مثال زیر، مثالی بسیار ساده از چگونگی کارکردن پیشوندها در مارک آپ XAML است. پیشوند سفارشی در تگ عنصر ریشه تعریف می شود، و به اسمبلی ای که پکیچ می شود و با application قابل دسترسی است، مپ می شود. این اسمبلی حاوی تایپ NumericUpDown است، که برای ساپورت کاربرد عمومی XAML و همچنین استفاده از وراثت کلاس پیاده سازی می شود. نمونه ای از این کنترل NumericUpDown، بصورت عنصر شی تعریف می شود.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:custom="clr-namespace:NumericUpDownCustomControl;assembly=CustomLibrary"
>
<StackPanel Name="LayoutRoot">
<custom:NumericUpDown Name="numericCtrl1" Width="100" Height="60"/>
...
</StackPanel>
</Page>
رویدادها و کد پشتی XAML
اکثر برنامه های WPF هم حاوی مارک آپ XAML و هم کد پشتی است. در یک پروژه، XAML بصورت فایل .xaml نوشته می شود، و از یک زبان CLR از قبیل Microsoft Visual Basic یا C# برای نوشتن فایل کد پشتی استفاده می شود. وقتی یک فایل XAML بعنوان بخشی از برنامه نویسی WPF و مدل های application، کمپایل می شود، موقعیت فایل کد پشتی XAML از طریق تعیین فضای نامی و کلاسی بعنوان اتریبیوت عنصر ریشه XAML شناسایی می شود.
در مثال هایی که تا آلان آورده شده، چندین دکمه دیده اید، ولی هیچ کدام از این دکمه ها رفتار منطقی ای که مربوط به آنها باشد ندارند. مکانیزم ابتدایی در سطح application برای اضافه کردن رفتار به عنصر شی، استفاده از یک رویداد (event) موجود در کلاس عنصر و نوشتن یک handler برای آن رویداد است.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ExampleNamespace.ExamplePage">
<Button Click="Button_Click" >Click Me!</Button>
</Page>
Private Sub Button_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
Dim b As Button = e.Source
b.Foreground = Brushes.Red
End Sub
دقت کنید که فایل code-behind از فضاهای نامی ExampleNamespace استفاده می کند و ExamplePage را بعنوان کلاسی جزیی درون آن فضای نامی تعریف می کند. کمپایلر مارک آپ WPF، با مشتق کردن کلاسی از تایپ عنصر ریشه، کلاسی جزیی برای فایل XAML کمپایل شده ایجاد شد. وقتی کد پشتی ای ایجاد می کنید که همان کلاس جزیی را نیز تعریف می کند، کد خروجی در همان فضای نامی و کلاس application کمپایل شده ترکیب می شود.
عنصرهای نام دار XAML
بطور پیش فرض، نمونه شی ای که از طریق پردازش عنصر شی XAML در گراف شی ایجاد می شود، دارای identifier منحصر بفرد یا ریفرنس شی نیست. در مقابل، اگر کانستراکتوری را در در فرابخوانید، تفریباً همیشه از نتیجه کانستراکتور برای قراردادن متغیری برای نمونه ساخت شده استفاده می کنید، بطوریکه بعداً می توانید نمونه را در کدتان ریفرنس کنید. برای فراهم کردن دسترسی استاندارد به شی ای که از طریق تعریف مارک آپ ایجاد شده، XAML اتریبیوت x:Name را تعریف می کند. می توانید مقدار اتریبویت x:Name را روی هر عنصر شی تنظیم کنید. در کد پشتی تان، Identifier انتخابی شما، معادل متغیر نمونه ایست که به نمونه ساخته شده refer میزشود.
عنصرهای XAML در سطح قالب کاری WPF، پراپرتی Name را به ارث می برند، که معادل اتریبیوت x:Name تعریف شده XAML است. بعضی کلاس های دیگر، معادل های در سطح پراپرتی برای x:Name فراهم می کنند که عموماً بصورت پراپرتی Name تعریف می شوند. اگر نتوانید پراپرتی Name را در جدول اعضای تایپ یا عنصر منتخب تان پیدا کنید، در عوض می توانید از x:Name استفاده کنید. مقدارهای x:Name، یک identifier برای عنصر XAML که می توان هنگام اجرا استفاده کرد، فراهم می کند.
مثال زیر، یک Name روی عنصر StackPanel تنظیم می کند. سپس یک Buttonدرون آن StackPanel، آن را از طریق ریفرنس نمونه اش یعنی buttonContainer، همانگونه که توسط Name تنظیم شده، ریفرنس می کند.
<StackPanel Name="buttonContainer">
...
<Button Click="RemoveThis">Click to remove this button</Button>
</StackPanel>
درست مثل یک متغیر، نام XAML برای نمونه توسط مفهوم scope مدیریت می شود، بطوریکه نام ها را می توان درون اسکوپی که قابل پیش بینی است، تحمیل کرد تا منحصر بفرد باشند. مارک آپ ابتدایی که صفحه را تعریف می کند، اسکوپ نامی منحصربفردی را با مرز اسکوپ نامی XAML که عنصر ریشه آن صفحه است، اهدا می کند.ُ اما دیگر منابع مارک آپ می توانند با صفحه ای هنگام اجرا تعامل داشته باشند.
پراپرتی ها و رویدادهای الصاق شده
XAML، ویژگی ای از زبان را تعیین می کند که بعضی از پراپرتی ها یا رویدادها را قادر به شناخته شدن روی هر عنصری می کند، بدون توجه به اینکه آیا آن پراپرتی یا رویداد در تعاریف تایپ برای عنصری که رویش تنظیم شده وجود دارد یا خیر. ورژن پراپرتی های این ویژگی، پراپرتی الصاق شده (attached property)، و ورژن رویداد های این ویژگی، رویداد الصاق شده (attached event) نامیده می شود. می توان پراپرتی ها و رویدادهای الصاق شده را اعضای جهانی در نظر گرفت که روی هر نمونه عنصر یا شی XAML تنظیم می شوند. اما آن کلاس یا عنصر یا زیربنای بزرگتر باید پراپرتی پشتیبان را برای مقادیر الصاق شده ساپورت کند.
پراپرتی های الصاق شده در XAML معمولاً توسط سینتکس اتریبیوت مورد استفاده قرار می گیرند. در سینتکس اتریبیوت، باید یک پراپرتی الصاق شده در فرم ownerType.propertyName تعیین کنید.
رایج ترین سناریو برای پراپرتی های الصاق شده، فعال کردن عنصرهای child برای گزارش کردن مقدار پراپرتی به عنصر parent است.
مثال زیر، پراپرتی الصاق شده DockPanel.Dock را نشان می دهد. کلاس DockPanel، اکسسورهای DockPanel.Dock را تعریف می کند، و بنابراین مالک پراپرتی الصاق شده محسوب می شود. همچنین کلاس DockPanel، حاوی منطقی است که عنصرهای child را تکرار می کند و هر عنصر را برای مجموعه ای از مقدارهای DockPanel.Dock چک می کند. اگر valueیی پیدا شود، آن مقدار (value) هنگام layout برای موقعیت یابی عنصرهای child مورد استفاده قرار می گیرد. استفاده از پراپرتی الصاق شده DockPanel.Dock و قابلیت موقعیت یابی در حقیقت به سناریوی کلاس DockPanel انگیزه می دهد.
<DockPanel>
<Button DockPanel.Dock="Left" Width="100" Height="20">I am on the left</Button>
<Button DockPanel.Dock="Right" Width="100" Height="20">I am on the right</Button>
</DockPanel>
در WPF، اکثر یا همه پراپرتی های الصاق شده به صورت پراپرتی های مستقل نیز پیاده سازی می شوند.
رویدادهای الصاق شده نیز از فرم سینتکس اتریبیوت ownerType.eventName استفاده می کنند. درست مثل رویدادهای غیر الصاقی، مقدار اتریبیوت رویداد الصاق شده در XAML، نام متد هندلر را تعیین می کند. کاربرد رویداد الصاق شده در WPF XAML کمتر رایج است.
تایپ های پایه و XAML
WPF XAML پایه و فضای نامی XAML، مجموعه ای از تایپ هایی است که با اشیا CLR و عنصرهای مارک آپ XAML تطابق دارد. اما همه کلاس ها را نمی توان به عنصرها مپ کرد. از کلاس های انتزاعی مانند ButtonBase، و بعضی کلاس های غیرانتزاعی پایه برای وراثت در مدل اشیای CLR استفاده می شود. کلاس های پایه، شامل کلاس های انتزاعی هنوز برای توسعه XAML مهم هستند زیرا هر کدام از عنصرهای XAML واقعی، اعضایی را از بعضی کلاس های پایه در سلسله مراتبشان به ارث می برند. این اعضا اغلب حاوی پراپرتی هایی هستند که می توان بصورت اتریبیوت هایی روی عنصر یا رویدادهایی که می توان مدیریت کرد، تنظیم کرد. FrameworkElement، پایه واقعی کلاس UI در WPF در سطح قالب کاری WPF است. هنگام طراحی UI، باید از شکل، پنل، دکوراتور، یا کلاس های کنترل، که همگی از FrameworkElement مشتق می شوند، استفاده کنید. کلاس FrameworkContentElement، عنصرهای سند گرا را ساپورت می کند. این عنصرها در flow layout presentation، با استفاده از APIهایی که APIهای موجود در FrameworkElement را mirror می کنند، خوب کار می کنند. ترکیب اتریبیوت های در سطح عنصر و مدل شی CLR، مجموعه ای از پراپرتی های رایج را در اختیار شما قرار می دهد که در اکثر عنصرهای واقعی XAML، قابل تنظیم هستند.
امنیت XAML
XAML زبانی markup است که مستقیماً instantiation و execution شی را نمایش می دهد. بنابراین، عناصر ایجاد شده در XAML دارای قابلیتی یکسان برای تعامل با ریسورس های سیستم هستند.
WPF، از .NET Framework 4 security framework Code Access Security یا (CAS) ساپورت می کند. این بدین معناست که محتویات در حال اجرای WPF در اینترنت، permissionهای اجرا (execution) را کاهش داده است. "Loose XAML" (صفحه های کمپایل نشده XAML که زمان بارگذاری توسط یک XAML viewer تفسیر می شود)، و برنامه مرورگر XAML، معمولاً در ناحیه اینترنت اجرا می شوند و همچنان از همان مجموعه permissionها استفاده می کنند. اما، XAMLیی که در برنامه ای کاملاً مطمئن بارگذاری شده است، مانند برنامه های میزبان، همان دسترسی به ریسورس های سیستم را دارد.
بارگذاری XAML از کد
از XAML می توان برای تعریف همه UIها استفاده کرد. اما گاهی اوقات برای تعریف تنها بخشی از UI در XAML نیز مناسب است. از این قابلیت می توان برای فعال کردن سفارشی کردن جزیی، ذخیره محلی اطلاعات، استفاده از XAML برای فراهم کردن شی تجارت، یا سناریوهای ممکن دیگر استفاده کرد. کلید این سناریوها، کلاس XamlReade و متد Load است. ورودی (input)، یک فایل XAML، و خروجی (output)، شی ای است که کل tree زمان اجرای شی ای را که از آن مارک آپ ایجاد شده، نمایش می دهد. سپس می توانید شی را insert کنید تا پراپرتی شی دیگری باشد که از قبل در application وجود دارد. تا وقتی که پراپرتی، یک پراپرتی مناسب در مدل محتوایی باشد که قابلیت نمایش نهایی را دارد، و موتور اجرایی (execution engine) را مطلع می کند که محتوای جدیدی به برنامه اضافه شده است، می توانید محتوای در حال اجرای برنامه را به سادگی و از طریق بارگذاری در XAML اصلاح کنید. توجه داشته باشید که این قابلیت، بدلیل تاثیرات واضح امنیتی بارگذاری فایل ها در برنامه، هنگام اجرا، معمولاً فقط در برنامه های کاملاً مطمئن دردسترس است.