熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

開發基於Web的CSS設計器

2013-11-13 10:15:32  來源: .NET編程 
   這半年參與了一個基於的中型應用系統開發其間經歷種種收獲不少前段時間做了一個基於Web的CSS設計器雖然技術不算復雜不過綜合了C#/XML/HTC等技術對於大家應該有一定參考價值而且該設計器相對於系統比較獨立因此在這裡和大家共享供大家參考並請多提意見! 

   設計器的主要功能就是在web界面上設計操作CSS樣式表目的是方便用戶自定義系統界面

   相信做過Web開發的人大多用過Dreamweaver或者做開發也應該用過那麼應該熟悉裡面的樣式(style)設計器這裡就是在Web上實現這個設計器


  


系統流程

下面我們先來了解一下整個系統流程


流程再簡單說明一下

·先傳入參數包括文件名/樣式名/操作方法/可視化樣式元素其中可視化樣式元素是要在設計器中即時顯現供效果預覽的同時也是承載樣式定義內容的要素(樣式就加載在元素的style屬性上)

·然後設計器根據傳入參數操作根據操作方法新建文件/新建樣式/修改樣式前兩者在初始化時不用讀取樣式文件最後者需要讀取樣式進行初始化利用一個設計的C#類來對樣式文件和樣式類進行操作

·在客戶端利用Javascript操作XmlDocument對象讀取XML定義的樣式文件進行設計器構建

·利用Javascript通過樣式元素的cssText屬性讀取樣式值對設計器初始化

·用戶操作設計器利用HTC組件操作設計樣式

·保存利用C#類操作


CSS設計器之樣式表操作類 

下面我們來詳細察看流程的每個環節

為了操作樣式表設計了一個簡單的樣式表操作類功能主要是解析操作指定樣式表文件實現對樣式類的添加修改刪除保存 

機制讀取Web服務器上某樣式表文件將文本轉化為一個ArrayList數組元素為自定義的ClassItem對象包含Name和Text屬性(Name即樣式名稱Text即樣式的內容)然後通過對ArrayList操作控制樣式最後保存 

由於在服務器段我們不作具體樣式定義因此該類只操作到樣式類級別不涉及樣式屬性和值

下面提供該類的UML圖 ClassItem 是一個結構體僅包含兩個屬性

  





  按此在新窗口打開圖片

  CSS設計器之XML樣式屬性定義 

CSS樣式中包含很多屬性設置設計器中當然要包含相應的屬性那麼這些屬性信息從哪裡來呢? 

采用XML定義是一種很自然就會想到的方式 

經常使用DW和VSNET所以在交互設計上采用了類似的模式先將樣式屬性按應用分類再設置詳細屬性 

CSS屬性是比較復雜的如果要完全按照DW或VSNET的模式實現會比較復雜為了簡化我把值的輸入簡化為兩種形式選擇和文本輸入對於選擇直接在XML文件中定義對於文本輸入抽象幾種輸入類型在設計器生成時根據類型設定不同的HTC組件操作這樣就將一些復雜的屬性輸入封裝到HTC組件中整個構架就簡潔起來 


XML文件描述 

首先是屬性分類 

<CSSDesign>
   <Category>
       <Name>文字</Name>
        <Style>
             <Name>字體</Name>
             
        </Style>
        <Style>
             <Name>樣式</Name>
             
        </Style>
           
   </Category>
   <Category>
       <Name>背景</Name>
        <Style>
             <Name>顏色</Name>
             
        </Style>
        
   </Category>
</CSSDesign>

    系統分為文字背景文本位置布局方框邊框和其他每種類型有一個Name子元素和若干Style子元素


每個Style子元素表示一個Style屬性結構如下 

<Style>
   <Name>字體</Name>
   <CssName>fontfamily</CssName>
   <ActionType>select</ActionType>
   <SelectItems>
      <Item>verdanaarial</Item>
      <Item Name=宋體>SimSun</Item>
      <Item Name=黑體>SimHei</Item>
   </SelectItems>
</Style>

<Style>
   <Name>大小</Name>
   <CssName>fontsize</CssName>
   <ActionType>select</ActionType>
   <SelectItems>
      <Item>px</Item>
      <Item>px</Item>
      <Item>px</Item>
   </SelectItems>
</Style>

<Style>
   <Name>顏色</Name>
   <CssName>background</CssName>
   <ActionType>input_ColorSelect</ActionType>
</Style>


Name 為該屬性的描述名稱在設計器中為文本描述 

CssName 為屬性名在設計器中即輸入字段的ID初始化時也據此賦值 

ActionType 為屬性設置方法在設計器中為輸入字段的樣式類名該樣式中含有Behavior屬性制定HTC組件 

SelectItems 為選擇項如果ActionType為Select將會在此列出選擇項其子元素Item如果含有Name屬性將顯示在設計器中否則直接顯示該元素的文本內容 


框架圖


  按此在新窗口打開圖片

  CSS設計器之界面交互

整個操作交互過程除了最後保存文件外其他都是由javascript完成 

首先DesignerBuild函數通過XmlDocumnet讀取XML樣式屬性定義文件構建整個設計器界面然後Init函數讀取服務器端賦給設計元素的StylecssText屬性並把屬性作為輸入控件ID在設計器中查找並賦值完成初始化 

在操作過程中根據輸入控件的樣式類Class觸發綁定的HTC組件做相應的客戶端操作 

最後再讀取設計元素的style屬性保存 


設計器界面 

  按此在新窗口打開圖片


不同的設計元素

  按此在新窗口打開圖片


不同輸入控件的不同class屬性(根據XML中ActionType生成)觸發不同HTC組件實現不同輸入模式

  按此在新窗口打開圖片


  按此在新窗口打開圖片


  按此在新窗口打開圖片

  由於商業原因這裡不便提供源代碼我將在後面提供部分關鍵代碼供參考

  程序代碼

  這裡對前面文章講的CSS設計器系統關鍵代碼作一些小結如果沒有看過前面文章的請先參看開發基於Web的CSS設計器


解析CSS樣式文件

這段代碼主要作用是把CSS文件分解為多個樣式類並按名稱/文本屬性生成ClassItem對象並保存在一個ArrayList(cssList)中(C#代碼)

//讀取文件
FileInfo theSource= new FileInfo (@m_filePath);
StreamReader reader = theSourceOpenText();
//將文件流轉化為文本
m_cssText = readerReadToEnd();
readerClose();
//定義CSS文本分割符
char[] delimiters = new char[] { {}};
int iCheck = ;
string className = null;
//將文本轉化為ArrayList
foreach ( string substring in m_cssTextSplit(delimiters))
{
    if (iCheck%==)
        //當iCHeck為偶數時字符串為樣式屬性內容
        //將解析的樣式名和屬性作為ClassItem對象存入cssList
        cssListAdd( new ClassItem ( className substringTrim() ) );
    else
        //當iCHeck為奇數時字符串為樣式名暫存
        className = substringTrim();
    iCheck++;
}
 

交互界面構建

交互界面由Javascript通過XmlDocument讀取Xml文件動態生成

首先要讀取XML文件然後遍歷整個XML文件先遍歷樣式分類再對每個分類遍歷其下的所有樣式屬性比較關鍵的代碼是對XML的遍歷下面是對樣式分類的遍歷代碼


//LoadXML是XML文件讀取函數
var dom = LoadXML(cssxml); 
//通過XPath和selectNodes方法返回一個XMLDOMNodeList對象
var oNode = domselectNodes(//Category/Name);
//獲取該對象長度即XML文檔中該路徑節點的數量
var intCategory = oNodeslength; 
for (i=; i<intCategory; i++)
{
   //獲取集合中的節點
   oNode = oNodesnextNode;
   if (oNode != null)   
   {
  //樣式分類界面構建代碼
   …… 
   }
}

 


樣式輸入控件構建函數該函數作用是根據XPath路徑查詢XML定義生成交互控件


function BuildInput ( path )
{
   var str=;
   var aNode=null;
   var attValue=null;
   //通過selectSingleNode返回符合條件的第一個節點
   var actNode = domselectSingleNode(path+ActionType);
   var nameNode = domselectSingleNode(path+CssName);
   //如果屬性為選擇輸入則讀取SelectItems並構建select控件
   if (actNodetext==select)
   {
      str += <select id=+nameNodetext+ name=+nameNodetext+ class=eSelect>\n;
      
      //查詢該項的所有選擇列表項
       var itemsNodes = domselectNodes (path+SelectItems/Item);
      str += <option value=>未設置</option>\n;
      for (ii=;ii<itemsNodeslength;ii++)
      {
         aNode = domselectSingleNode (path+SelectItems/Item[+ii+]);
         
         //如果該項含有Name屬性則在列表中顯示Name屬性值
          attValue = aNodegetAttribute(Name)
         var txtNode = domselectSingleNode (path+SelectItems/Item[+ii+]);

         if (attValue==null)
            str += <option value=+txtNodetext+>+txtNodetext+</option>\n;
         else
            str += <option value=+txtNodetext+>+attValue+</option>\n;
      }
      
      str += </select>;
   }
   else
   
   //如果屬性為其他模式則構建input輸入設置class屬性為ActionType
   {
      str = <input name=+nameNodetext+ id=+nameNodetext+ class=+actNodetext+>\n;
   }
   
   return(str);
}

 

  設計器初始化

Js腳本讀取解析樣式元素的style屬性值然後為設計器中構建的控件賦值


//設計器初始化
function Init()
{
   //獲得由服務器端賦值的樣式屬性值
   var txt=documentall(DemoShow)stylecssText;
   if (txtlength>)
   {
      var strClassName;
      
      //解析字符串
       var aryClass = txtsplit(/[:;]/);
      for( i in aryClass)
      {
         var str = aryClassreplace(/(^\s*)|(\s*$)/g );
         if(!(i%==))
         {
            //當i為奇數時解析的字符串應該為樣式屬性名稱
            strClassName=str;
         }
         else
         {
            //當i為偶數時獲得屬性值
              //屬性名稱即控件ID
            //判斷該屬性對應的控件是輸入框還是選擇列表            
            if(documentall(strClassName)type==selectone)
            {
               
               //如果是選擇列表通過setIndexOfValue函數設定選擇項
               setIndexOfValue(strClassNamestr);
               
            }
            else
            {
               documentall(strClassName)value=str;
            }
         }
         i++;
      }
   }
}

 
界面交互

在XML中一共定義了select/input_ColorSelect/input_SizeSelect/input_BorderSelect(後種為顏色/大小/邊框輸入模式)共種輸入模式除select為直接選擇外其他在對應控件初始化的時候作為class屬性賦值到控件中類似class代碼如下 


/* 顏色輸入模式input框的樣式類 */
input_ColorSelect{
width:px;
fontfamily:Tahoma;
behavior:url(htc/effColorSelecthtc);
}

通過behavior屬性把該輸入控件和相應的組件相關聯該組件effColorSelecthtc代碼如下


<PUBLIC:ATTACH EVENT=onfocus ONEVENT=getShow()/>
<PUBLIC:METHOD NAME=getChange/>
<SCRIPT LANGUAGE=JScript
function getShow()
{
   elementblur();
   
   //記錄當前交互控件的ID
   effElement=elementid;
   //在頁面中加載輸入控件
   ShowControl (SelectColor);
}

function getChange()
{
   //當值發生變化時對可視化樣式元素賦值
   SetAttribute(elementidelementvalue);
}
</SCRIPT> 


其他

設計器中的值輸入模式框只是頁面中的幾個層通過上面的htc組件觸發顯示出來輸入後再把值傳入到樣式屬性控件中同時也會設置可視化樣式元素 

另外還需要注意的是XML文檔是可以自行擴展或縮減的但是在實際應用中不能完全依據CSS標准來定義因為可視化元素的style屬性會自動格式化例如如果你在XML中定義borderbottomwidth屬性在將值取出時會自動格式化為borderbottom這樣會造成設計器中控件不能匹配我在MSDN沒有查到相關文檔所以只有經過實際測試來驗證 


OK比較關鍵的代碼已經差不多了……希望能對大家有所幫助 


參考

另外再列出部分技術參考如果大家對其中的技術細節如HTC和XmlDom等有所疑問可以再詳細研究一下也歡迎大家來和我交流   

MSDN關於JS操作XmlDom的文檔
這是英文文檔網上沒有看到比較詳細的中文文檔好在不復雜大家將就一下吧 :)
(最近MSDN不知道什麼毛病經常訪問有問題如果無法訪問請先登錄msdn再輸入地址浏覽)

藍色理想的HTC教程 
網上也沒看見比較全面的講述這個簡單易學基本概念清楚了 


From:http://tw.wingwit.com/Article/program/net/201311/13085.html
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.