1. ML是XAML的一个应用。
例1:一个合法片段,展现了控件以及element的嵌套层次结构:
< StackPanel >< Button Foreground ="LightSeaGreen" FontSize ="24pt" > //指定attributeHello, XAML! //指定property(content)</ Button >< Ellipse Fill ="Brown" Width ="200" Height ="100" /> //没有property< Button >< Image Source ="http://www.charlespetzold.com/PetzoldTattoo.jpg" Stretch ="None" /></ Button ></ StackPanel >
- 指定WPF程序所需的命名空间,我们利用“xmlns”这个attribute来声明默认的XML命名空间。此命名空间会被应用于声明出现的element以及其下的每个孩子
WPF命名空间指定方法: xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
例2:一个完整的XMAL文件内容:
< Button xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" // 指定WPF命名空间Foreground ="LightSeaGreen" FontSize ="24pt" >Hello, XAML!</ Button >
2. 关于root element
XML 文件只能有一个root element, 它可以是继承自FrameworkElement的任何类,但是不能是Window
3. 如何在c#代码中解析XAML
- WPF程序使用XamlReader.Load将一段XAML转成一个对象,如果此XAML的根element具有子element,这些element会一并被转换,并放到visual tree中。
但是,XamlReader.Load 不能直接接受字符串作为参数,只能接收Stream,或者一个XmlReader对象。
例3:将XAML定义为字符串并解析
代码
using System;
using System.IO;
using System.Windows;
using System.Windows.Markup;
using System.Xml;
namespace Petzold.LoadEmbeddedXaml
{
public class LoadEmbeddedXaml : Window
{
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run( new LoadEmbeddedXaml());
}
public LoadEmbeddedXaml()
{
Title = " Load Embedded Xaml " ;
string strXaml =
" <Button xmlns='http://schemas.microsoft.com/ " +
" winfx/2006/xaml/presentation' " +
" Foreground='LightSeaGreen' FontSize='24pt'> " +
" Click me! " +
" </Button> " ;
StringReader strreader = new StringReader(strXaml);
XmlTextReader xmlreader = new XmlTextReader(strreader);
object obj = XamlReader.Load(xmlreader);
Content = obj;
}
}
}
如果需要获取此button并为其增加事件处理函数,可以如下处理:
Button btn = (Button) XamlReader.Load(xmlReader);
btn.Click+=ButtonClick;
- 如果需要将XAML文件作为资源加载,需要将该XAML文件的Build Action设置为:Resource
例4:在c#文件中加载并解析XAML文件。
首先,在project中“Add New Item”,加入一个如下XML文件,命名为:LoadXamlResource
< StackPanel xmlns = " http://schemas.microsoft.com/winfx/2006/xaml/presentation " >
< Button Name ="MyButton"
HorizontalAlignment = " Center "
Margin = " 24 " >
Hello, XAML !
</ Button >
< Ellipse Width = " 200 "
Height = " 100 "
Margin = " 24 "
Stroke = " Red "
StrokeThickness = " 10 " />
< ListBox Width = " 100 "
Height = " 100 "
Margin = " 24 " >
< ListBoxItem > Sunday </ ListBoxItem >
< ListBoxItem > Monday </ ListBoxItem >
< ListBoxItem > Tuesday </ ListBoxItem >
< ListBoxItem > Wednesday </ ListBoxItem >
< ListBoxItem > Thursday </ ListBoxItem >
< ListBoxItem > Friday </ ListBoxItem >
< ListBoxItem > Saturday </ ListBoxItem >
</ ListBox >
</ StackPanel >
右击该文件,选择Property,确定Build Action为 Resource
在.cs文件中输入如下内容:
using System;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
namespace Petzold.LoadXamlResource
{
public class LoadXamlResource : Window
{
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run( new LoadXamlResource());
}
public LoadXamlResource()
{
Title = " Load Xaml Resource " ;
Uri uri = new Uri( " pack://application:,,,/LoadXamlResource.xml " );
Stream stream = Application.GetResourceStream(uri).Stream;
FrameworkElement el = XamlReader.Load(stream) as FrameworkElement;
Content = el;
Button btn = el.FindName("MyButton") as Button;
if (btn != null )
btn.Click += ButtonOnClick;
}
void ButtonOnClick( object sender, RoutedEventArgs args)
{
MessageBox.Show( " The button labeled ' " +
(args.Source as Button).Content +
" ' has been clicked " );
}
}
}
代码分析:
首先通过静态属性Application.GetResourceStream获取一个StreamResourceInfo对象,该对象包含一个Stream属性,便得到了XML资源。
然后通过XamlReader.Load将资源转换成对象,再设为Window的Content, 变成窗口视觉树的一部分
最后通过FindName方法在书中找出特定名称的element,也就是Button, 并添加相应的事件处理函数。
- 例5:一个通过对话框加载XAML的程序实例
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Xml;
using Microsoft.Win32;
namespace Petzold.LoadXamlFile
{
public class LoadXamlFile : Window
{
Frame frame;
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run( new LoadXamlFile());
}
public LoadXamlFile()
{
Title = " Load XAML File " ;
DockPanel dock = new DockPanel();
Content = dock;
// Create button for Open File dialog.
Button btn = new Button();
btn.Content = " Open File... " ;
btn.Margin = new Thickness( 12 );
btn.HorizontalAlignment = HorizontalAlignment.Left;
btn.Click += ButtonOnClick;
dock.Children.Add(btn);
DockPanel.SetDock(btn, Dock.Top);
// Create Frame for hosting loaded XAML.
frame = new Frame();
dock.Children.Add(frame);
}
void ButtonOnClick( object sender, RoutedEventArgs args)
{
OpenFileDialog dlg = new OpenFileDialog();
dlg.Filter = " XAML Files (*.xaml)|*.xaml|All files (*.*)|*.* " ;
if (( bool )dlg.ShowDialog())
{
try
{
// Read file with XmlTextReader.
XmlTextReader xmlreader = new XmlTextReader(dlg.FileName);
// Convert XAML to object.
object obj = XamlReader.Load(xmlreader);
// If it's a Window, call Show.
if (obj is Window)
{
Window win = obj as Window;
win.Owner = this ;
win.Show();
}
// Otherwise, set as Content of Frame.
else
frame.Content = obj;
}
catch (Exception exc)
{
MessageBox.Show(exc.Message, Title);
}
}
}
}
}
4. XAML文件和code behind文件
- XAML文件中,WPF命名空间和XAML命名空间
一般,我们会指定WPF element的命名空间为默认的命名空间:
xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
WPF只是XAML的一种可能的应用方式,如果要使用XAML专用的element和attribute,需要第二个命名空间的声明:
xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml
如果需要自定义class,需要添加如下的命名空间:
- 为支持定义在XAML文件中的控件和element,会需要一个code behind的c#文件:
public namespace MyNamespace
{
public partial class MyClassName: Window
{
...
}
}
partial关键字意味着该文件只是此class的一部分,在其他地方还有代码。