WPF XAML(二)

发布时间:2024年01月17日

一、前言

本文是 WPF XAML(一)的续文,链接我就放下面了。

WPF XAML(一)-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_71897293/article/details/135537094?spm=1001.2014.3001.5501

二、XAML 中空白与特殊字符

????????在XAML中我们在设计程序的时候可能需要对文本进行一些空格或换行或者是输入 < >这样的特殊符号。但我们受到XML规则限制,都无法直接设置等操作。

举个例子:

  <TextBlock
      HorizontalAlignment="Center"
      VerticalAlignment="Center"
      FontSize="25">
      文      本
  </TextBlock>
  <TextBlock
      HorizontalAlignment="Center"
      VerticalAlignment="Center"
      FontSize="25" >
      文
          本
  </TextBlock>

示例解释:

????????我们如果想显示多个空格显示效果为:文 ? ? ?本 但实际显示效果则是:文 本?。原因就在我们XAML中如果我们设置多个空格或者插入TAB 换行等都视为一个空格。在文本前后添加的所有空格也将忽略

效果:

解决当前问题 为元素使用??xml:space="preserve"?特性

举个例子:

<TextBlock
    HorizontalAlignment="Center"
    VerticalAlignment="Center" xml:space="preserve"
    FontSize="25" >
    文
        本
</TextBlock>

?示例解释:当前将会保留所有空格和文本的前后空格以及换行效果。

补充:如果是直接设置显示的文本的属性或者后台代码设置内容都将保留所有的空格。?


使用特殊符号举个例子我们想显示 <文本>的内容

举个例子:

  <!--<TextBlock
      HorizontalAlignment="Center"
      VerticalAlignment="Center"
      FontSize="25">
      <文本>
  </TextBlock>-->
  <TextBlock
      HorizontalAlignment="Center"
      VerticalAlignment="Center"
      FontSize="25">
      &lt;文本 &gt;
  </TextBlock>
  <TextBlock
      HorizontalAlignment="Center"
      VerticalAlignment="Center"
      FontSize="25">
      小于号 &lt; 大于号 &gt; 符号 &amp; 引号 &quot;
  </TextBlock>

?示例解释:

? ? ? ? 在第一个TextBlock元素他将无法通过编译,因为<文本>编译器会以为你是想创建文本这个元素,或者是说”创建文本对象“。

? ? ? ? 第二个采用特殊符号就可以显示上述文本:”<文本>“?

? ? ? ? 第三个是我给出的几种特殊符号的写法。

效果:

三、使用其他名称空间的内容

问:为什么要使用其他名称空间的内容?

答:1有时我们想将其他类型对象提取信息绑定到我门的控件属性上? 2是使用其他类型为WPF 对象设置属性。

举个例子(使用自定义类型填充WPF 对象属性):

  public class Person
  {
      public string Age { get; set; }
  }
<Window
    x:Class="WpfApp5.MainWindow"
    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:local="clr-namespace:WpfApp5"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="800"
    Height="450"
    mc:Ignorable="d">
    <ListBox DisplayMemberPath="Age">
        <local:Person Age="15" />
    </ListBox>
</Window>

示例解释:

? ? ? ? ?我们定义了一个自定义的类Person我们可以用它作为我们的wpf对象的属性进行填充,比如我们将当前这个类作为ListBox的填充内容。其中我们给当前对象设置了相应的属性并设置了list books当中的项如何显示内容,显示内容为Age。

????????如果试图创建简单的基本类型(如字符串、日期或数字类型),可提供数据的字符串表示形式作为标签中的内容。XAML 解析器按着将使用类型转换器将符串转换为合适的对象。

举个例子:

<Window
    x:Class="WpfApp5.MainWindow"
    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:local="clr-namespace:WpfApp5"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    Title="MainWindow"
    Width="800"
    Height="450"
    mc:Ignorable="d">
    <ListBox>
        <sys:DateTime>2003/11/01 12:10 AM</sys:DateTime>
    </ListBox>
</Window>

示例解释:

????????sys 是希望在XAML标记中用于指示名称空间的XML前缀。例如,XAML语言使用x前缀。clr-namespace:System;是完全限定的NET名称空间的名称,assembly是声明类型的程序集,没有dll 扩展名。这个程序集必须在项目中用。如果希望使用项目程序集,可忽略这一部分。如Datetime是在mscorlib程序集中所有需要指定当前程序集。


提问:

问:怎么知道数据的程序集

答:可以反编译查看到。


?????????

效果预览:?

四、加载和编译XAML?

???????完全可以创建不使用XAML的WPF 应用程序可使用三种不同的编码方式来创建WPF应用程序:

?????????只使用代码。这是在 Visual Studio 中为 Windows 窗体应用程序使用的传统方法。它通过代码语句生成用户界面。
????????使用代码和未经编译的标记(XAML)。这种具体方式对于某些特殊情况是很有意义的例如创建高度动态化的用户界面。这种方式在运行时使用 System.Windows.Markup 名称空间中的XamIReader类,从XAML文件中加载部分用户界面。
????????使用代码和编译过的标记(BAML)对于 WPF 而言这是一种更好的方式,也是 VisualStudio支持的一种方式。这种方式为每个窗口创建一个XAML模板,这个XAML 模板被编译为 BAML,并嵌入到最终的程序集中。编译过的 BAML 在运行时被提取出来用于重新生成用户界面。

一、举个例子(只使用代码):

1新建一个WPF程序 删除MainWindow.xaml??App.xaml 如下图

2 添加一个启动类?StartApp:

 [STAThread]
 static void Main()
 {
     new MyWindow().ShowDialog();
 }

3 添加窗体类,窗体类中的代码如下

 public class MyWindow : Window
 {
     public MyWindow()
     {
         InitializeComponent();
     }
     private Button button;
     private void InitializeComponent()
     {
         //设置窗体属性
         this.Title = "代码创建";

         //设置元素内容
         button = new Button();
         button.Content = "Click";
         button.Click += Button_Click;
         StackPanel stackPanel = new StackPanel();
         stackPanel.Children.Add(button);
         IAddChild addChild = stackPanel;

         this.Content = addChild;

     }

     private void Button_Click(object sender, RoutedEventArgs e)
     {
         MessageBox.Show("Hello");
     }
 }

示例解释:?IAddChild 是一个?使得你能够动态地向 XAML 元素添加子元素,这是通过?AddChild?和?AddLogicalChild?方法实现的。

运行效果:

?二、使用代码和未经编译的标记(XAML)

举个例子:

1 先创建一个WIndow窗体文件,我们可以在XAML设计器中设计后复制到记事本在将记事本保存格式改为.XAML在添加到项目中。

<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:sys="clr-namespace:System;assembly=mscorlib">
    <ListBox Name="list">
        <ListBoxItem>
            <sys:DateTime>2003/11/01 12:10 AM</sys:DateTime>
        </ListBoxItem>
        <ListBoxItem>
            <sys:DateTime>2003/11/01 12:10 AM</sys:DateTime>
        </ListBoxItem>
        <ListBoxItem>
            <sys:DateTime>2003/11/01 12:10 AM</sys:DateTime>
        </ListBoxItem>
    </ListBox>
</Grid>

如上代码我们复制到记事本,在将记事本保存格式改为.XAML在添加到项目中。?

如图所示:

然后修改XAML文件的属性

2 我们继续使用我们前面使用到的MyWindow类,做一点修改。

    private void InitializeComponent()
    {
        //设置窗体属性
        this.Title = "代码创建";

        DependencyObject dependencyObject;
        //获取元素
        using (FileStream fileStream = new FileStream("MainWindow.Xaml", FileMode.Open))
        {
            dependencyObject = (DependencyObject)XamlReader.Load(fileStream);
        }
        //以下是两种方法
        //1--
        //查找具有适当名称的控件。.
        listBox = (ListBox)LogicalTreeHelper.FindLogicalNode(dependencyObject, "list");//返回类型 DependencyObject
        listBox.SelectionChanged += ListBox_SelectionChanged;
        //2--
        //装换为FrameworkElement类型 调用自身的FindName方法
        //FrameworkElement frameworkElement = (FrameworkElement)rootElement;
        //button1 = (Button)frameworkElement.FindName("button1");
        //设置元素内容
        button = new Button();
        button.Content = "Click";
        button.Width = 100;
        button.Height = 100;
        button.Click += Button_Click;

        if (dependencyObject is Grid grid)
        {
            grid.Children.Add(button);
            this.Content = dependencyObject;
        }
        else
        {
            StackPanel stackPanel = new StackPanel();
            stackPanel.Children.Add(button);
            IAddChild addChild = stackPanel;
            this.Content = addChild;
        }

    }

    private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        MessageBox.Show((sender as ListBox).SelectedItem.ToString());
    }

示例解释:

????????XamlReader就是读取当前用方法将这个文件中的内容转换成DcpendcncyObjcct 对象,DcpendencyObjcct 是所有 WPF 控件继承的基类DependencyObjcct对象可放在任意类型的容器中。?查找具有适当名称的控件。LogicalTreeHelper.FindLogicalNode 第一个是.DcpendcncyObjccte类型参数,第二个是当前要查找的控件元素名称。


????????解释一下为什么这是使用代码和未经编译的标记(XAML)的示例。因为,我先将XAML 编译为BAML,再在运行时加载BAML, 我们这里是没有经过我们的编译器编译过的,所以这是一个使用代码和未编译的标记的示例。

这样会比动态加载XAML的效率高,当用户界面比较复杂时尤其如此。

运行效果:

三、使用代码和编译过的标记(BAML)

?????????这里我们在前面的示例如:使用其他名称空间的内容,就是一个典型的示例。其中我需要补充几点。

? ? ? ?1 在运行时读取 BAML 比读取 XAML的速度要快部署更简单。

????????2 因为 BAML 作为一个或多个资源嵌入到程序集中,不会丢失。

????????3可在其他程序中编辑 XAML 文件,例如设计工具。这为程序编程人员和设计人员之间更好地开展协作提供了可能(当使用未编译的XAML时,也能获得这个好处,如上一节所)。

文章来源:https://blog.csdn.net/qq_71897293/article/details/135581880
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。