欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

WindowsPhone自定义控件详解(二) - 模板类库分析

程序员文章站 2022-12-25 14:10:54
windowsphone自定义控件详解(一) - 控件类库分析 上一节主要分析了控件类库,控件类之间的继承关系,通过继承关系,可以知道一些属性,事件的源头和机制。   本节开始介绍模板类库...

windowsphone自定义控件详解(一) - 控件类库分析
上一节主要分析了控件类库,控件类之间的继承关系,通过继承关系,可以知道一些属性,事件的源头和机制。

 

本节开始介绍模板类库,并加实例。

基类自定义时都要用到模板,在框架中所有的模板都是frameworktemplate的子类如下图,包括:

 controltemplate
itemspaneltemplate
datatemplate
通过上述文字的分析,你已经可以理解为什么有上面的三种模板了吧。

 

下面分别来解释三种模板。

 

一、 模板类详解

 

继承关系:

 WindowsPhone自定义控件详解(二) - 模板类库分析

 

由上图可知,控件对象模板,项集合模板和数据对象模板都是继承自frameworktemplate类,

1. controltemplate主要用于自定义控件的操作行为和视图结构的外观显示效果。如:当按钮按下时如何显示等,按钮上要不要同时显示图片和文本。

通过设置控件的template属性(继承自control)来应用自定义的controltemplate
2.  itemspaneltemplate主要用于自定义带有列表项的控件中各子控件的布局外观显示效果,如:listbox中的列表项怎样对布局。

通过设置控件的itemspanel属性来应用自定义的itemspaneltemplate
3.  datatemplate主要用于自定义内容控件中的数据视图效果,如:listbox中每一项显示什么数据。

 通过设置控件的itemtemplate /contenttemplate属性来应用自定义的datatemplate,注意:一个控件上可能应用多个自定义模板,如:listbox设置listbox的列表项items为横向排列,设置每个列表项里布局和数据,这样就要设置listbox的itemspaneltemplate和datatemplate。
 
controltemplate类
  定义控件的视图显示模板,从而可以对控件进行自定义。在模板内可以构建自己的控件对象树。

注意:

如果您正在定义一个控件模板来取代一个现有控件类的模板,则您用于定义控件模板内容的 xaml 应与现有的控件匹配。否则,该控件可能无法在用户界面中正常发挥作用。
不能将 controltemplate 应用于 usercontrol(前面有说明为什么)。
例如为 button 创建一个简单的 controltemplate。控件模板包含一个 grid 并指定以下行为:

·         当用户将鼠标悬停在 button 上方时,grid 在半秒之后从绿色变为红色。

·         当用户将鼠标移离按钮时,grid 立即变回到绿色。

 

[html] <controltemplate targettype="button"> 
  <grid > 
    <visualstatemanager.visualstategroups> 
      <visualstategroup x:name="commonstates"> 
        <visualstategroup.transitions> 
          <!--take one half second to trasition to the mouseover state.--> 
          <visualtransition to="mouseover" generatedduration="0:0:0.5"/> 
        </visualstategroup.transitions> 
        <visualstate x:name="normal" /> 
        <!--change the solidcolorbrush, buttonbrush, to red when the 
            mouse is over the button.--> 
        <visualstate x:name="mouseover"> 
          <storyboard> 
            <coloranimation storyboard.targetname="buttonbrush"  
        storyboard.targetproperty="color" to="red" /> 
          </storyboard> 
        </visualstate> 
      </visualstategroup> 
    </visualstatemanager.visualstategroups> 
    <grid.background> 
      <solidcolorbrush x:name="buttonbrush" color="green"/> 
    </grid.background> 
  </grid> 
</controltemplate> 
<controltemplate targettype="button">
  <grid >
    <visualstatemanager.visualstategroups>
      <visualstategroup x:name="commonstates">
        <visualstategroup.transitions>
          <!--take one half second to trasition to the mouseover state.-->
          <visualtransition to="mouseover" generatedduration="0:0:0.5"/>
        </visualstategroup.transitions>
        <visualstate x:name="normal" />
        <!--change the solidcolorbrush, buttonbrush, to red when the
            mouse is over the button.-->
        <visualstate x:name="mouseover">
          <storyboard>
            <coloranimation storyboard.targetname="buttonbrush"
  storyboard.targetproperty="color" to="red" />
          </storyboard>
        </visualstate>
      </visualstategroup>
    </visualstatemanager.visualstategroups>
    <grid.background>
      <solidcolorbrush x:name="buttonbrush" color="green"/>
    </grid.background>
  </grid>
</controltemplate>
 

 

itemspaneltemplate 类
itemspaneltemplate定义itemscontrol中的item项布局的模板。itemscontrol 的默认值是一个指定 stackpanel的 itemspaneltemplate。例如:listbox是一个itemscontrol子控件,它的item项布局模板itemspaneltemplate为默认的stackpanel,而stackpanel默认布局是垂直布局,因此,默认的listbox的item项垂直布局的,当我们向listbox里添加item时,都是垂直列表形式,如果你想要自定义你的listbox风格为水平显示,那么将要自定义itemspaneltemplate里stackpanel为水平方向。

如下例,将listbox的风格改为水平子项显示方式。

 

模板xaml:

[html] <grid> 
  <grid.resources> 
    <style x:key="horizontallistboxstyle" targettype="listbox"> 
      <setter property="itemspanel"> 
        <setter.value> 
          <itemspaneltemplate> 
            <stackpanel orientation="horizontal" 
              verticalalignment="center" 
              horizontalalignment="center"/> 
          </itemspaneltemplate> 
        </setter.value> 
      </setter> 
    </style> 
<src:items x:key="items"/> 
  </grid.resources> 
  <listbox itemssource="{staticresource items}"  
           style="{staticresource horizontallistboxstyle}"/> 
</grid> 
<grid>
  <grid.resources>
    <style x:key="horizontallistboxstyle" targettype="listbox">
      <setter property="itemspanel">
        <setter.value>
          <itemspaneltemplate>
            <stackpanel orientation="horizontal"
              verticalalignment="center"
              horizontalalignment="center"/>
          </itemspaneltemplate>
        </setter.value>
      </setter>
    </style>
<src:items x:key="items"/>
  </grid.resources>
  <listbox itemssource="{staticresource items}"
           style="{staticresource horizontallistboxstyle}"/>
</grid>
 
 

c#代码:

[csharp] public class items :  
    system.collections.objectmodel.observablecollection<string> 

    public items() 
    { 
        add("item 1"); 
        add("item 2"); 
        add("item 3"); 
        add("item 4"); 
        add("item 5"); 
    } 

public class items :
    system.collections.objectmodel.observablecollection<string>
{
    public items()
    {
        add("item 1");
        add("item 2");
        add("item 3");
        add("item 4");
        add("item 5");
    }
}
 
显示效果如下:

 WindowsPhone自定义控件详解(二) - 模板类库分析
 

总结:

itemspaneltemplate主要用于带有item项的控件风格布局模板设置,常见的控件就是listbox,

 datatemplate 类
  用于定义内容控件内数据对象的可视结构模板。虽然内容控件只能包含一个uielement但是,它可以包含一个容器控件,从而可以间接的包含多个子控件,而datacontent就是为这些容器控件里的子控件进行布局的模板类。

下面的例子,自定了listbox中每一项中的ui如何表现。每一个item中包含四个水平布局的textblock控件,每个textblock控件都绑定了customers的属性。

xaml:

[html] <grid> 
    <grid.resources> 
        <src:customers x:key="customers"/> 
    </grid.resources> 
 
    <listbox itemssource="{staticresource customers}" width="350" margin="0,5,0,10"> 
        <listbox.itemtemplate> 
            <datatemplate> 
                <stackpanel orientation="horizontal"> 
                    <textblock padding="5,0,5,0" 
                       text="{binding firstname}" /> 
                    <textblock text="{binding lastname}" /> 
                    <textblock text=", " /> 
                    <textblock text="{binding address}" /> 
                </stackpanel> 
            </datatemplate> 
        </listbox.itemtemplate> 
    </listbox> 
</grid> 
<grid>
    <grid.resources>
        <src:customers x:key="customers"/>
    </grid.resources>

    <listbox itemssource="{staticresource customers}" width="350" margin="0,5,0,10">
        <listbox.itemtemplate>
            <datatemplate>
                <stackpanel orientation="horizontal">
                    <textblock padding="5,0,5,0"
                       text="{binding firstname}" />
                    <textblock text="{binding lastname}" />
                    <textblock text=", " />
                    <textblock text="{binding address}" />
                </stackpanel>
            </datatemplate>
        </listbox.itemtemplate>
    </listbox>
</grid>

 

c#:

[csharp] public class customer 

    public string firstname { get; set; } 
    public string lastname { get; set; } 
    public string address { get; set; } 
 
    public customer(string firstname, string lastname, string address) 
    { 
        this.firstname = firstname; 
        this.lastname = lastname; 
        this.address = address; 
    } 

 
public class customers : observablecollection<customer> 

    public customers() 
    { 
        add(new customer("michael", "anderberg", 
                "12 north third street, apartment 45")); 
        add(new customer("chris", "ashton", 
                "34 west fifth street, apartment 67")); 
        add(new customer("cassie", "hicks", 
                "56 east seventh street, apartment 89")); 
        add(new customer("guido", "pica", 
                "78 south ninth street, apartment 10")); 
    } 

public class customer
{
    public string firstname { get; set; }
    public string lastname { get; set; }
    public string address { get; set; }

    public customer(string firstname, string lastname, string address)
    {
        this.firstname = firstname;
        this.lastname = lastname;
        this.address = address;
    }
}

public class customers : observablecollection<customer>
{
    public customers()
    {
        add(new customer("michael", "anderberg",
                "12 north third street, apartment 45"));
        add(new customer("chris", "ashton",
                "34 west fifth street, apartment 67"));
        add(new customer("cassie", "hicks",
                "56 east seventh street, apartment 89"));
        add(new customer("guido", "pica",
                "78 south ninth street, apartment 10"));
    }
}
 

 

二、其它


datacontext类

 WindowsPhone自定义控件详解(二) - 模板类库分析

 

datacontext是frameworkelement的属性,是object类型,用于获取或设置 frameworkelement 参与数据绑定时的数据上下文。也就是说它是被数据绑定的对象。

datacontext也就是第四代控件祖宗的属性(说实话,控件从第三代祖宗uielement开始才有了外观,有了点人样),

如果你给它绑定了数据源,clr就会从数据源里拿出对应数据用于显示,datacontext有传递性,如果外部包含控件设置了datacontext,被包含控件没有设置该属性,则被包含控件也可以使用外部包含控件的datacontext。

比如:

 xaml:

[html] <phone:phoneapplicationpage.resources> 
            <local:weibodata x:key="myweibodata"/> 
</phone:phoneapplicationpage.resources> 
 
<grid x:name="layoutroot" background="transparent"  datacontext="{staticresource myweibodata}"> 
        <stackpanel grid.row="0" margin="12,17,0,28"> 
            <textblock x:name="datetextblock" text="{binding weibodate}" > 
            <textblock x:name="titletextblock" text="{binding weibotitle}" /> 
        </stackpanel> 
</grid> 
<phone:phoneapplicationpage.resources>
            <local:weibodata x:key="myweibodata"/>
</phone:phoneapplicationpage.resources>

<grid x:name="layoutroot" background="transparent"  datacontext="{staticresource myweibodata}">
        <stackpanel grid.row="0" margin="12,17,0,28">
            <textblock x:name="datetextblock" text="{binding weibodate}" >
            <textblock x:name="titletextblock" text="{binding weibotitle}" />
        </stackpanel>
</grid>
 

 

weibodata类中包含有weibodate属性和weibotitle属性,虽然没有指定两个textblock的绑定对象,但是它有grid控件的datacontext。

 在后续两节,我们分别以这两节的知识,分享两个不错的例子:

自定义水印密码输入控件和下拉刷新控件。

注:上述两个控件经常使用并且方便快捷,经常用于微博等经常刷新的地方。

 

摘自 mr_raptor的专栏