当前位置: 移动技术网 > IT编程>移动开发>WP > WindowsPhone自定义控件详解(二) - 模板类库分析

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

2018年10月08日  | 移动技术网IT编程  | 我要评论

盲目溪谷,项城网,秦原微博

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

 

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

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

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

 

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

 

一、 模板类详解

 

继承关系:

 \

 

由上图可知,控件对象模板,项集合模板和数据对象模板都是继承自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");
    }
}
 
显示效果如下:

 \
 

总结:

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类

 \

 

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的专栏

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网