久久亚洲成a人片熟女精品色一区二区三区|国产精品视频第一精品视频|av天堂热无码手机版|亚洲?v无码久久无遮挡|国产精品偷伦视频免费观看国产|麻豆国产自产精品丰满熟妇|av无码av不卡一区二区|久久亚洲精品中文字

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營的一線實(shí)戰(zhàn)洞察。

WPF界面框架分層實(shí)踐:主題Token、MVVM與換膚避坑

WPF界面框架分層實(shí)踐:主題Token、MVVM與換膚避坑 簡介面向 WPF 桌面應(yīng)用開發(fā)者的一套現(xiàn)代化界面框架源碼與示例適合希望擺脫默認(rèn)控件外觀、快速搭建統(tǒng)一視覺風(fēng)格的中級開發(fā)者參考也可作為團(tuán)隊(duì) UI 規(guī)范與主題定制的基礎(chǔ)。壓縮包約 1.84MB共 336 個(gè)文件以 143 個(gè) C# 源碼與 115 個(gè) XAML 界面文件為主體另含 15 個(gè) csproj 工程文件、圖標(biāo)與圖片素材、Visual Studio 項(xiàng)目模板及少量說明文檔覆蓋控件實(shí)現(xiàn)、窗口外殼、主題資源到可復(fù)用模板的完整鏈路。目前已有 6464 人學(xué)習(xí)下載。內(nèi)容圍繞現(xiàn)代化窗口、菜單、對話框與過渡動(dòng)畫控件展開涉及主題外觀管理與系統(tǒng)版本適配等模塊可據(jù)此理解樣式模板、資源字典與 MVVM 在真實(shí)項(xiàng)目中的組織方式并直接改造為自己的應(yīng)用外殼。1. 一個(gè)漂亮的 WPF 界面框架漂亮之外到底解決什么問題上個(gè)月幫一個(gè)內(nèi)部工具做收尾功能全跑通了評審時(shí)被一句話打回來這套 WPF 界面看著像十年前的。真正動(dòng)手改才發(fā)現(xiàn)難點(diǎn)不在畫得好看而在主色散落在二十多個(gè) XAML 里、按鈕存在三套模板、每個(gè)窗口的標(biāo)題欄各寫各的。這份 WPF 界面框架源碼包就是把這堆散件整理成三層主題 Token、控件模板、窗口外殼再配一套 MVVM 骨架和若干示例頁。它主要解決兩件具體的事改一處顏色不用翻遍工程新頁面照著示例拼就能交付。適合正在用 WPF 做桌面端、要把界面從「能跑」推到「能驗(yàn)收」的人不適合想找拖拽式設(shè)計(jì)器、指望完全不寫 XAML 的人。2. 拆目錄結(jié)構(gòu)主題 Token、控件模板、窗口外殼這三層怎么分拿到一個(gè)界面框架先別急著運(yùn)行 Demo也別急著往自己的工程里復(fù)制。先看Themes目錄的層次因?yàn)樗鼪Q定了后面所有覆蓋、換膚、定制動(dòng)作能不能生效。這套框架的劃分是比較典型的做法Tokens放純值顏色、字號、圓角、間距、控件高度Controls放控件樣式與ControlTemplateSkins放皮膚覆蓋Shell放窗口外殼與標(biāo)題欄。分層的意義在于職責(zé)邊界清晰Token 里不該出現(xiàn)任何ControlTemplate控件模板里不該出現(xiàn)任何寫死的#2F6FED。我見過太多項(xiàng)目的資源字典是一個(gè)幾千行的Styles.xaml顏色、模板、動(dòng)畫、轉(zhuǎn)換器全塞在一起。這種文件在項(xiàng)目第三個(gè)月就會(huì)變成黑匣子誰都不敢刪任何一行因?yàn)椴恢绖h了會(huì)影響哪個(gè)頁面。分層不是潔癖是為了讓你敢改。2.1 先看資源字典的合并順序它決定后面所有覆蓋能不能生效WPF 在MergedDictionaries里查找同一個(gè) Key 時(shí)后加入的字典優(yōu)先級更高。這條規(guī)則很短但它是整套換膚機(jī)制的基石。很多人的皮膚切換做不出來原因就一個(gè)把皮膚字典加在了 Token 字典前面于是 Token 里的舊值一直勝出換膚看起來「沒反應(yīng)」。正確的合并順序是先 Token再 Controls最后 Skin。!-- App.xamlxmlns 省略實(shí)際工程里按模板生成的寫 -- Application.Resources ResourceDictionary ResourceDictionary.MergedDictionaries !-- 第 1 層純值沒有任何模板。換膚就是換這一層的值 -- ResourceDictionary SourceThemes/Tokens/Colors.Default.xaml/ ResourceDictionary SourceThemes/Tokens/Typography.xaml/ ResourceDictionary SourceThemes/Tokens/Metrics.xaml/ !-- 第 2 層控件模板只允許引用第 1 層的 Key -- ResourceDictionary SourceThemes/Controls/Button.xaml/ ResourceDictionary SourceThemes/Controls/TextBox.xaml/ ResourceDictionary SourceThemes/Controls/Card.xaml/ !-- 第 3 層皮膚覆蓋第 1 層同名 Key必須放最后 -- ResourceDictionary SourceThemes/Skins/Light.xaml/ /ResourceDictionary.MergedDictionaries /ResourceDictionary /Application.Resources這段順序背后有兩條必須記住的規(guī)則。第一條是查找方向MergedDictionaries的檢索是從后往前所以最后加載的皮膚能蓋住前面所有同名 Key。第二條是作用域Application.Resources是全局的窗口和控件會(huì)逐級向上查找一旦某一層出現(xiàn)了同名 Key上層的就永遠(yuǎn)取不到——調(diào)試時(shí)「樣式在別的頁面正常、就這個(gè)頁面不對」八成是這個(gè)頁面的Window.Resources里藏了一個(gè)同名項(xiàng)。跨程序集引用時(shí)路徑要改成 pack URI比如pack://application:,,,/YourApp;component/Themes/Tokens/Colors.Default.xaml程序集名寫錯(cuò)的話運(yùn)行時(shí)會(huì)拋IOException而不是編譯錯(cuò)誤這也是常見的第一道問題。2.2 顏色、字號、圓角三組 Token為什么主色要用 DynamicResourceToken 層只做一件事把「設(shè)計(jì)決定」變成「命名常量」。這套框架里大致是三類鍵名前綴即語義分類示例 Key典型值說明顏色Color.Accent.Base#2F6FED主色另配 Hover、Pressed 兩檔顏色Color.Surface.Card#FFFFFF卡片、面板底色字號Font.Size.Body13正文另有 Caption 12、Title 18圓角Radius.Control6按鈕、輸入框統(tǒng)一圓角間距Space.Unit8所有間距取它的整數(shù)倍尺寸Metric.Control.Height32單行控件標(biāo)準(zhǔn)高度主色不要只給一個(gè)值Hover 和 Pressed 要手調(diào)出來別用Opacity疊。原因是透明疊加的結(jié)果依賴背景色同一個(gè)按鈕放在白色卡片和深色側(cè)欄上淺色疊加出來的效果完全不同深色背景上會(huì)發(fā)灰。這是很常見的視覺問題單看沒問題一放到深色區(qū)域就顯得臟。!-- Tokens/Colors.Default.xaml -- ResourceDictionary xmlns... xmlns:x... !-- 主色三檔Hover/Pressed 手工調(diào)深保證在深色和淺色背景上都成立 -- Color x:KeyColor.Accent.Base#2F6FED/Color Color x:KeyColor.Accent.Hover#245BD0/Color Color x:KeyColor.Accent.Pressed#1C48A8/Color !-- Brush 單獨(dú)一層控件模板里用 Brush換膚時(shí)只換 Brush 即可 -- SolidColorBrush x:KeyBrush.Accent.Base Color{StaticResource Color.Accent.Base}/ SolidColorBrush x:KeyBrush.Accent.Hover Color{StaticResource Color.Accent.Hover}/ SolidColorBrush x:KeyBrush.Text.OnAccent Color#FFFFFF/ SolidColorBrush x:KeyBrush.Surface.Card Color#FFFFFF/ !-- 字號與度量數(shù)值型 Token 用 sys:Double必須帶命名空間 -- sys:Double x:KeyFont.Size.Body13/sys:Double sys:Double x:KeyFont.Size.Title18/sys:Double CornerRadius x:KeyRadius.Control6/CornerRadius sys:Double x:KeyMetric.Control.Height32/sys:Double /ResourceDictionary關(guān)鍵在于「顏色」和「畫筆」分成兩層。Color是不可變結(jié)構(gòu)體SolidColorBrush才是控件屬性真正吃的東西模板里引用的必須是 Brush。數(shù)值型 Token 要注意類型x:Double需要引入sys命名空間clr-namespace:System;assemblySystem.Runtime不同目標(biāo)框架程序集名略有差異CornerRadius直接寫元素即可不用額外命名空間?,F(xiàn)在說DynamicResource和StaticResource怎么選這是最常被問的一個(gè)問題。結(jié)論是會(huì)隨皮膚變化的 Key 用DynamicResource永不變的 Key 用StaticResource。StaticResource在 XAML 解析時(shí)就把值取出來定死換膚后不會(huì)重新求值所以把主色用StaticResource引到模板里切皮膚必然失敗DynamicResource每次取值走一次資源查找會(huì)帶來額外開銷在DataGrid單元格模板、ItemsControl項(xiàng)模板這種會(huì)實(shí)例化成千上萬次的地方能靜態(tài)就靜態(tài)。我的習(xí)慣是Token 里跟顏色相關(guān)的全用DynamicResource字號、圓角、間距這類換膚不動(dòng)的用StaticResource。這個(gè)劃分一句話能記住后面維護(hù)的人也不會(huì)亂改。2.3 拆一個(gè)按鈕從 Token 到 ControlTemplate 的完整鏈路理解了層次再拆一個(gè)具體控件看看這套框架里一個(gè)主按鈕是怎么拼起來的。這段值得逐行讀因?yàn)樗呛竺嫠锌丶哪0濉?-- Controls/Button.xaml只引用 Token不出現(xiàn)任何字面色值 -- Style x:KeyButton.Primary TargetTypeButton Setter PropertyHeight Value{StaticResource Metric.Control.Height}/ Setter PropertyMinWidth Value72/ Setter PropertyPadding Value16,0/ Setter PropertyFontSize Value{StaticResource Font.Size.Body}/ Setter PropertyForeground Value{DynamicResource Brush.Text.OnAccent}/ Setter PropertyBackground Value{DynamicResource Brush.Accent.Base}/ Setter PropertyBorderThickness Value0/ Setter PropertyCursor ValueHand/ Setter PropertyTemplate Setter.Value ControlTemplate TargetTypeButton Border x:NameBd Background{TemplateBinding Background} CornerRadius{StaticResource Radius.Control} SnapsToDevicePixelsTrue ContentPresenter HorizontalAlignmentCenter VerticalAlignmentCenter Margin{TemplateBinding Padding} RecognizesAccessKeyTrue/ /Border ControlTemplate.Triggers !-- 順序有講究后定義的觸發(fā)器優(yōu)先級更高 -- Trigger PropertyIsMouseOver ValueTrue Setter TargetNameBd PropertyBackground Value{DynamicResource Brush.Accent.Hover}/ /Trigger Trigger PropertyIsPressed ValueTrue Setter TargetNameBd PropertyBackground Value{DynamicResource Brush.Accent.Pressed}/ /Trigger Trigger PropertyIsEnabled ValueFalse Setter TargetNameBd PropertyOpacity Value0.45/ Setter PropertyCursor ValueArrow/ /Trigger /ControlTemplate.Triggers /ControlTemplate /Setter.Value /Setter /Style這里有幾個(gè)容易被忽略的細(xì)節(jié)每一個(gè)都可能變成后期幾分鐘甚至幾小時(shí)地去排查的問題。第一TemplateBinding是單向的、不支持轉(zhuǎn)換器且只能綁到模板化父級的屬性上。所以Padding能綁Background能綁但如果你想把Background轉(zhuǎn)成漸變就必須換成{Binding Background, RelativeSource{RelativeSource TemplatedParent}}再掛 Converter?;煊眠@兩者時(shí)不要抱有僥幸心理模板里一旦出現(xiàn)轉(zhuǎn)換需求就整體換成Binding。第二觸發(fā)器順序決定最終效果。IsMouseOver和IsPressed同時(shí)為真時(shí)后定義的IsPressed生效所以按下色必須寫在懸停色后面。反過來寫按下時(shí)看到的還是懸停色看起來就像「按下沒反饋」。第三IsEnabledFalse時(shí)如果只改OpacityCursorHand依然生效鼠標(biāo)移上去還是手型用戶會(huì)以為可以點(diǎn)。所以禁用態(tài)要順手把Cursor也改回來這類細(xì)節(jié)在驗(yàn)收時(shí)最容易被挑出來。最后控件模板里不要出現(xiàn)字面色值這是硬性約束。只要模板里出現(xiàn)一個(gè)#2F6FED換膚那一刻它就會(huì)變成色塊不一致的元兇而且很難靠肉眼定位到具體是哪個(gè)模板??蚣芾镞@類違規(guī)用一次文本搜索就能找出來接入前先搜一遍#順手清理掉。3. 接入現(xiàn)有工程從復(fù)制目錄到跑出第一個(gè)頁面3.1 目錄落位與 csproj 里的資源聲明把整個(gè)工程復(fù)制進(jìn)來是最快的驗(yàn)證方式但真正接入現(xiàn)有項(xiàng)目時(shí)建議只復(fù)制Themes和Infrastructure兩個(gè)目錄示例頁按需挑選著拿。目錄放在項(xiàng)目根下即可不要塞進(jìn)Properties或者obj旁邊obj目錄在清理時(shí)容易誤刪。csproj這塊有個(gè)高頻問題SDK 風(fēng)格工程的默認(rèn) glob 已經(jīng)把**/*.xaml編譯成Page你再手寫一遍Page IncludeThemes\**\*.xaml /就會(huì)報(bào)重復(fù)項(xiàng)NETSDK1022。所以大部分情況下什么都不用寫只在需要排除或者改變構(gòu)建方式時(shí)才動(dòng)它。ItemGroup !-- 默認(rèn) glob 已包含 **/*.xaml這里只做排除草稿目錄不參與編譯 -- Page RemoveThemes\_draft\**\*.xaml / !-- 字體、圖標(biāo)這類二進(jìn)制資源用 Resource隨程序集嵌入pack URI 才取得到 -- Resource IncludeAssets\Fonts\*.ttf / Resource IncludeAssets\Icons\*.png / !-- 示例數(shù)據(jù)用 Content 復(fù)制到輸出目錄別用 Resource 塞進(jìn)程序集 -- Content IncludeSampleData\*.json CopyToOutputDirectoryPreserveNewest / /ItemGroup構(gòu)建項(xiàng)的選擇直接決定資源能不能取到這張表建議存下來構(gòu)建項(xiàng)編譯結(jié)果適用場景取用方式Page編譯為 BAML所有 XAML包括資源字典Source相對路徑Resource嵌入程序集字體、圖標(biāo)、小圖片pack://application:,,,/程序集;component/路徑Content原樣復(fù)制到輸出目錄示例數(shù)據(jù)、可替換配置相對輸出目錄的路徑None不處理文檔、說明無字體用Resource嵌入之后在 XAML 里通過FontFamily/Assets/Fonts/#字體內(nèi)部名引用注意斜杠后面那個(gè)#后面跟的是字體家族名不是文件名。寫錯(cuò)了不會(huì)報(bào)錯(cuò)只會(huì)靜默回退到系統(tǒng)默認(rèn)字體——這類靜默失敗最耗時(shí)間。3.2 App.xaml 合并字典與運(yùn)行時(shí)換膚皮膚切換不要用「先清空再添加」的寫法。清空MergedDictionaries會(huì)在瞬間讓所有DynamicResource失效控件重繪時(shí)可能拋出找不到資源的異常而「只添加不移除」會(huì)讓字典越積越多切換五十次之后內(nèi)存和查找開銷都會(huì)肉眼可見地上漲。正確做法是把皮膚字典固定在MergedDictionaries的最后一位換膚就是替換這一項(xiàng)。public static class ThemeManager { // 皮膚字典固定放在 MergedDictionaries 的末位替換這一項(xiàng)即為換膚 private static readonly Uri LightSkin new(pack://application:,,,/YourApp;component/Themes/Skins/Light.xaml); private static readonly Uri DarkSkin new(pack://application:,,,/YourApp;component/Themes/Skins/Dark.xaml); public static void Apply(bool dark) { var merged Application.Current.Resources.MergedDictionaries; if (merged.Count 0) return; var skin new ResourceDictionary { Source dark ? DarkSkin : LightSkin }; // 關(guān)鍵替換而不是 Add避免字典無限增長 merged[merged.Count - 1] skin; } }替換完成后不需要手動(dòng)刷新任何控件DynamicResource會(huì)自動(dòng)重新求值。這里有個(gè)前提所有隨皮膚變化的引用必須是DynamicResource只要模板里漏了一個(gè)StaticResource換膚后那個(gè)控件就會(huì)保持舊色在一片新配色里顯得很突兀。還要注意換膚的時(shí)機(jī)。啟動(dòng)時(shí)在App構(gòu)造函數(shù)里調(diào)用是最穩(wěn)的如果放在窗口Loaded之后用戶會(huì)看到一次明顯的閃爍。真想做到無閃爍就得在窗口顯示前把皮膚定好也就是把配置讀取提前到App初始化階段。3.3 無邊框窗口外殼與自定義標(biāo)題欄這套框架的外殼用的是WindowChrome而不是WindowStyleNone加AllowsTransparencyTrue。后者雖然也能做出無邊框效果但會(huì)讓窗口失去硬件加速路徑拖動(dòng)和縮放時(shí)明顯發(fā)澀圓角邊緣還會(huì)有鋸齒。WindowChrome保留系統(tǒng)窗口的非客戶區(qū)行為只把繪制權(quán)交給你。!-- Shell/AppWindow.xaml無邊框外殼保留系統(tǒng)縮放與拖拽行為 -- Window x:ClassYourApp.Shell.AppWindow WindowStyleNone ResizeModeCanResize AllowsTransparencyFalse Background{DynamicResource Brush.Surface.Card} !-- CaptionHeight頂部可拖拽區(qū)高度等于標(biāo)題欄高度 -- !-- ResizeBorderThickness邊緣拖拽熱區(qū)觸屏場景建議放大到 8 -- WindowChrome.WindowChrome WindowChrome CaptionHeight40 ResizeBorderThickness6 GlassFrameThickness0 CornerRadius0 UseAeroCaptionButtonsFalse/ /WindowChrome.WindowChrome Grid Grid.RowDefinitions RowDefinition Height40/ RowDefinition Height*/ /Grid.RowDefinitions !-- 標(biāo)題欄區(qū)域內(nèi)的按鈕必須聲明 IsHitTestVisibleInChrome否則點(diǎn)不到 -- StackPanel Grid.Row0 OrientationHorizontal HorizontalAlignmentRight WindowChrome.IsHitTestVisibleInChromeTrue Button Content— Style{StaticResource Button.Caption}/ Button Content□ Style{StaticResource Button.Caption}/ Button Content× Style{StaticResource Button.Caption}/ /StackPanel ContentPresenter Grid.Row1 Content{Binding Body}/ /Grid /Window三個(gè)參數(shù)決定了使用手感。CaptionHeight要和標(biāo)題欄那一行的高度嚴(yán)格對齊寫 40 就是 40寫小了頂部會(huì)剩一條既不能拖也不能點(diǎn)的死區(qū)ResizeBorderThickness在鼠標(biāo)場景 6 夠了觸屏設(shè)備建議 8 到 10否則邊緣拖不動(dòng)GlassFrameThickness0去掉系統(tǒng)玻璃層避免深色皮膚下邊緣發(fā)亮。標(biāo)題欄里的按鈕必須加WindowChrome.IsHitTestVisibleInChromeTrue這一條不加按鈕會(huì)變成「看得見點(diǎn)不著」鼠標(biāo)事件被拖拽區(qū)吃掉了。這是無邊框窗口最常見的一個(gè)問題排查時(shí)容易往命令綁定上想繞一圈才發(fā)現(xiàn)是命中測試。另一個(gè)是最大化蓋住任務(wù)欄。無邊框窗口最大化時(shí)系統(tǒng)給的尺寸包含非工作區(qū)直接鋪滿會(huì)頂?shù)羧蝿?wù)欄。簡單的做法是在窗口構(gòu)造里設(shè)MaxHeight SystemParameters.MaximizedPrimaryScreenHeight多顯示器場景下這個(gè)值只在主屏正確需要監(jiān)聽WM_GETMINMAXINFO自己算工作區(qū)框架的Shell目錄里有對應(yīng)的輔助類接入時(shí)按屏幕數(shù)量確認(rèn)一下。3.4 驗(yàn)收入口DPI、縮放、多屏的檢查清單界面框架接進(jìn)去功能點(diǎn)兩下都正常不代表能交付。下面這張表是我每次接入必過的一遍成本不到十分鐘能提前擋掉大部分返工。檢查項(xiàng)操作不通過的表現(xiàn)單屏 100%系統(tǒng)縮放調(diào)到 100%逐頁翻一遍1px 邊框消失或變粗單屏 150%縮放到 150%看文字與圖標(biāo)文字發(fā)虛、圖標(biāo)模糊多屏不同縮放兩屏分別設(shè) 100% 和 150%拖窗口來回拖到另一屏后整體變糊高對比度切換系統(tǒng)高對比度主題文字與背景同色看不見觸摸觸屏設(shè)備上點(diǎn)邊緣縮放邊緣拖不動(dòng)最小尺寸拖到最小寬高標(biāo)題欄按鈕被擠出可視區(qū)DPI 那一欄解釋一下WPF 是邏輯像素體系縮放變化時(shí)如果圖片資源只準(zhǔn)備了一份系統(tǒng)會(huì)拉伸結(jié)果就是模糊。圖標(biāo)盡量用矢量路徑位圖則按 100%、150%、200% 各備一份靠Image的尺寸選擇邏輯去匹配。這條不做用戶在 150% 縮放的筆記本上第一眼就會(huì)覺得「這軟件有點(diǎn)舊」。4. MVVM 骨架命令、通知、導(dǎo)航與對話框怎么切界面層的活干完接著看骨架。這套框架的Infrastructure目錄里放的是一套很薄的基礎(chǔ)設(shè)施ViewModelBase、RelayCommand、AsyncCommand、導(dǎo)航服務(wù)、對話框服務(wù)。判斷一套 MVVM 骨架好不好標(biāo)準(zhǔn)只有一條ViewModel 里能不能完全不出現(xiàn)Window、MessageBox、Application.Current。出現(xiàn)了單測就廢了復(fù)用也別想了。4.1 ViewModelBase屬性通知與 SetProperty 的寫法public abstract class ViewModelBase : INotifyPropertyChanged { public event PropertyChangedEventHandler? PropertyChanged; // 返回 bool方便 setter 里鏈?zhǔn)酵ㄖ缮鷮傩?protected bool SetPropertyT(ref T field, T value, [CallerMemberName] string? name null) { // 用 EqualityComparer 而不是 object.Equals避免值類型裝箱 if (EqualityComparerT.Default.Equals(field, value)) return false; field value; OnPropertyChanged(name); return true; } protected void OnPropertyChanged([CallerMemberName] string? name null) PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); }CallerMemberName省掉了手寫屬性名字符串改屬性名時(shí)不會(huì)漏改通知。相等判斷用EqualityComparerT.Default而不是因?yàn)榉盒屠飳χ殿愋褪茄b箱比較屬性高頻更新時(shí)這點(diǎn)開銷會(huì)積少成多。返回bool是個(gè)很實(shí)用的小設(shè)計(jì)if (SetProperty(ref _name, value)) OnPropertyChanged(nameof(DisplayName));這樣派生屬性只在真正變化時(shí)通知避免無謂的綁定刷新。老項(xiàng)目里常見的寫法是 setter 里連續(xù)調(diào)三次OnPropertyChanged每次輸入都觸發(fā)一輪完整重算。集合屬性是另一個(gè)問題點(diǎn)。ObservableCollectionT不要每次賦值都new那等于讓ItemsControl重建整個(gè)視圖樹滾動(dòng)位置會(huì)跳回頂部。正確做法是初始化一次之后用Clear()加Add()更新。4.2 RelayCommand 與 AsyncCommandCanExecute 刷新時(shí)機(jī)的坑public sealed class RelayCommand : ICommand { private readonly Actionobject? _execute; private readonly Funcobject?, bool? _canExecute; public RelayCommand(Actionobject? execute, Funcobject?, bool? canExecute null) { _execute execute ?? throw new ArgumentNullException(nameof(execute)); _canExecute canExecute; } public bool CanExecute(object? parameter) _canExecute?.Invoke(parameter) ?? true; public void Execute(object? parameter) _execute(parameter); public event EventHandler? CanExecuteChanged { add CommandManager.RequerySuggested value; remove CommandManager.RequerySuggested - value; } // 手動(dòng)觸發(fā)異步命令結(jié)束、集合變化后必須調(diào) public void RaiseCanExecuteChanged() CommandManager.InvalidateRequerySuggested(); }CommandManager.RequerySuggested是隱式刷新只在鍵盤、鼠標(biāo)等輸入事件之后觸發(fā)。這意味著如果你在后臺(tái)線程里改了某個(gè)標(biāo)志位按鈕的可用狀態(tài)可能要等到用戶點(diǎn)一下別的地方才更新。血淚經(jīng)驗(yàn)是異步命令執(zhí)行完畢、批量數(shù)據(jù)加載完成這類時(shí)刻必須顯式調(diào)一次RaiseCanExecuteChanged()否則用戶會(huì)看到「按鈕還是灰的但功能其實(shí)已經(jīng)好了」。異步命令額外要處理兩件事。一是防重入執(zhí)行中把CanExecute置為false避免用戶連點(diǎn)三次發(fā)出三個(gè)請求。二是異常兜底async void里拋出的異常會(huì)直接打到未處理異常上進(jìn)程就掛了??蚣芾锏腁syncCommand用try/catch包住執(zhí)行體把異常交給注入的錯(cuò)誤處理器再由它彈提示。public sealed class AsyncCommand : ICommand { private readonly Funcobject?, Task _execute; private readonly Funcobject?, bool? _canExecute; private bool _isRunning; // 防重入標(biāo)志 public AsyncCommand(Funcobject?, Task execute, Funcobject?, bool? canExecute null) { _execute execute; _canExecute canExecute; } public bool CanExecute(object? parameter) !_isRunning (_canExecute?.Invoke(parameter) ?? true); public async void Execute(object? parameter) { if (_isRunning) return; _isRunning true; RaiseCanExecuteChanged(); try { await _execute(parameter); } catch (Exception ex) { // 必須兜住async void 里的異常無處可去 ErrorHandler?.Invoke(ex); } finally { _isRunning false; RaiseCanExecuteChanged(); } } public event ActionException? ErrorHandler; public event EventHandler? CanExecuteChanged; public void RaiseCanExecuteChanged() CanExecuteChanged?.Invoke(this, EventArgs.Empty); }AsyncCommand我沒有復(fù)用CommandManager而是自己維護(hù)CanExecuteChanged。原因是異步場景下按鈕狀態(tài)變化跟輸入事件沒有必然關(guān)系走隱式刷新容易失準(zhǔn)自己控制雖然要多調(diào)幾次RaiseCanExecuteChanged但行為可預(yù)期。4.3 導(dǎo)航與對話框接口怎么切才不綁死 UI接口切分的目標(biāo)是讓 ViewModel 只描述「要什么」不描述「怎么顯示」。這張表是框架里的切法接口職責(zé)不該做的事INavigationService按 ViewModel 類型切換主區(qū)域內(nèi)容不引用具體Page、Window類型IDialogService確認(rèn)框、輸入框、等待提示不直接調(diào)MessageBoxINotificationService頂欄消息、Toast不持有具體控件的引用IThemeService讀取與切換皮膚不碰Application.Resources的索引public interface IDialogService { // 返回 Task調(diào)用方 await 之后拿結(jié)果避免回調(diào)地獄 Taskbool ConfirmAsync(string title, string message); Taskstring? PromptAsync(string title, string message, string? defaultValue null); }實(shí)現(xiàn)側(cè)常見的做法是用一個(gè)覆蓋全窗口的ContentControl加半透明遮罩把對話框內(nèi)容當(dāng)作普通控件渲染返回值靠TaskCompletionSourcebool在用戶點(diǎn)擊時(shí)SetResult。這樣對話框也吃同一套 Token深色皮膚下不會(huì)出現(xiàn)一個(gè)白底黑字的系統(tǒng)彈窗視覺上跳出來。這里要提醒一點(diǎn)TaskCompletionSource必須用TaskCreationOptions.RunContinuationsAsynchronously否則SetResult會(huì)在 UI 線程上同步跑完整個(gè)await后續(xù)邏輯遇到重活就卡界面。這個(gè)問題非常隱蔽表現(xiàn)為「點(diǎn)確認(rèn)之后界面頓一下」把選項(xiàng)加上就好。5. 避坑記錄樣式不生效、內(nèi)存上漲、DPI 模糊的排查順序這一章是這份框架里最值得先讀的部分。下面四條都是我在真實(shí)接入里遇到過的每一條按現(xiàn)象、原因、解決的順序?qū)懹龅酵悊栴}時(shí)可以照著順序查。5.1 現(xiàn)象改了 Token控件紋絲不動(dòng)現(xiàn)象把Color.Accent.Base從藍(lán)改成橙重新生成主按鈕還是藍(lán)的。清緩存、重啟 IDE 都試過仍然是藍(lán)。原因控件模板里引用的是{StaticResource Brush.Accent.Base}。StaticResource在 BAML 解析階段就把值取出來寫死了后續(xù)字典變化對它沒有任何影響。另一種可能是這個(gè)頁面的Window.Resources里定義了一個(gè)同名的Brush.Accent.Base局部作用域優(yōu)先全局的改動(dòng)被它遮住。解決在解決方案里搜StaticResource Brush.凡是顏色類的引用全部換成DynamicResource再逐頁檢查Window.Resources和UserControl.Resources里有沒有同名 Key。這兩步做完改動(dòng)立即生效。我的習(xí)慣是把這條寫進(jìn)代碼評審清單模板里出現(xiàn)StaticResource后面跟Brush.前綴的一律打回。5.2 現(xiàn)象切幾次皮膚內(nèi)存一路往上走現(xiàn)象在設(shè)置頁反復(fù)切換淺色和深色任務(wù)管理器里的內(nèi)存從 180MB 漲到 400MB 不回落切得越多漲得越多。原因換膚實(shí)現(xiàn)寫成了merged.Add(skin)每次切換都往MergedDictionaries里追加一個(gè)字典舊字典既沒被移除也沒被回收資源查找還得從后往前遍歷一長串。另一個(gè)隱性原因是畫筆沒凍結(jié)SolidColorBrush每次創(chuàng)建都是新的可凍結(jié)對象沒調(diào)Freeze()就參與變更通知無法被共享。解決換膚改成替換末位元素見 3.2 的寫法Token 里所有SolidColorBrush在創(chuàng)建后調(diào)一次Freeze()凍結(jié)后的畫筆可以被多個(gè)控件共享內(nèi)存占用會(huì)明顯下降。改完再測反復(fù)切換五十次內(nèi)存曲線基本走平。提示Freeze()只能用于可凍結(jié)對象而且凍結(jié)后不能再改屬性。如果某個(gè)畫筆需要在運(yùn)行時(shí)調(diào)色就別凍結(jié)它。5.3 現(xiàn)象4K 屏上字體發(fā)虛、1px 邊框消失現(xiàn)象開發(fā)機(jī) 100% 縮放一切正常換到 150% 縮放的筆記本上正文明顯發(fā)糊卡片之間的 1px 分隔線時(shí)有時(shí)無圓角處還有毛邊。原因三個(gè)疊加問題。位圖圖標(biāo)只準(zhǔn)備了一份系統(tǒng)拉伸導(dǎo)致模糊Border的BorderThickness用了1但沒開UseLayoutRounding和SnapsToDevicePixels在非整數(shù)縮放比下 1px 被攤到兩個(gè)物理像素上顏色被稀釋到看不見再就是窗口設(shè)了AllowsTransparencyTrue透明窗口在部分縮放下失去硬件渲染路徑。解決圖標(biāo)改用矢量路徑在外殼根元素上開UseLayoutRoundingTrue需要像素對齊的Border和Image加SnapsToDevicePixelsTrue無邊框窗口換回WindowChrome方案。三條一起改150% 下再對比截圖邊緣和文字都恢復(fù)銳利。5.4 現(xiàn)象設(shè)計(jì)器里正常運(yùn)行時(shí)拋 XamlParseException現(xiàn)象XAML 在設(shè)計(jì)器里預(yù)覽得好好的一運(yùn)行就拋XamlParseException提示找不到某個(gè)資源堆棧指向一個(gè)看起來沒問題的Setter。原因StaticResource的解析是編譯期決定的它只能向前查找——引用必須出現(xiàn)在定義之后或者定義在更早就合并的字典里。設(shè)計(jì)器有時(shí)會(huì)更寬松地加載于是出現(xiàn)「設(shè)計(jì)器能看、跑起來就崩」。另一種原因是跨程序集引用時(shí) pack URI 里的程序集名寫錯(cuò)編譯期不校驗(yàn)運(yùn)行時(shí)才爆。解決先在App.xaml里把 Token 字典排在最前面確保所有模板在后面再檢查所有跨程序集的Source程序集名、大小寫、component關(guān)鍵字都要對上。定位技巧是把App.xaml里的合并字典臨時(shí)注釋掉一半二分法很快能鎖定是哪個(gè)文件。5.5 常見問題速查表癥狀第一嫌疑快速驗(yàn)證換膚后個(gè)別控件不變色模板里用了StaticResource全工程搜StaticResource Brush.按鈕點(diǎn)不動(dòng)標(biāo)題欄命中測試被吃檢查IsHitTestVisibleInChrome最大化蓋住任務(wù)欄無邊框窗口的尺寸計(jì)算看MaxHeight是否按工作區(qū)算列表刷新后滾動(dòng)條跳頂集合被整體new檢查ObservableCollection賦值處命令按鈕一直灰隱式刷新未觸發(fā)手動(dòng)調(diào)一次RaiseCanExecuteChanged字體不是預(yù)期那個(gè)FontFamily的家族名寫錯(cuò)核對#后面是家族名而非文件名6. 進(jìn)階把換膚做成可以回歸驗(yàn)證的流程界面類的改動(dòng)最難驗(yàn)證因?yàn)樗缚雌饋頉]問題」和「確實(shí)沒問題」之間差得很遠(yuǎn)。這套框架里我最常用的一個(gè)技巧是把換膚做成可以對比的回歸流程。第一步把 Token 抽出來做一份中間格式??蚣艿腡okens目錄本身就是鍵值對用幾十行代碼掃一遍 XAML把Color.*、Font.Size.*、Radius.*導(dǎo)出成 JSON交給設(shè)計(jì)側(cè)對齊。之后設(shè)計(jì)師改配色改的是這份 JSON工程師用腳本回寫 XAML比在群里發(fā)色值截圖靠譜得多?;貙懩_本要注意保留原有的x:Key順序和縮進(jìn)否則每次生成都是幾百行 diff評審時(shí)沒人看得下去。第二步準(zhǔn)備一個(gè)「Token 全覽頁」。把所有 Token 渲染成色塊、字號樣例、圓角樣例配上鍵名放在調(diào)試菜單里。換膚以后直接翻這一頁哪個(gè)鍵沒被覆蓋一眼就能看出來。這個(gè)頁面我一般不到半小時(shí)就能拼完但省下來的排查時(shí)間遠(yuǎn)超投入。第三步截圖比對。把關(guān)鍵頁面在淺色和深色下各截一張存在版本庫里改了樣式之后重新截用逐像素差值定位變化區(qū)域。閾值不要設(shè)在零字體渲染有亞像素抖動(dòng)允許千分之三以內(nèi)的差異超過就是真改了。這套流程跑順之后改一個(gè) Token 影響哪些頁面提交前就能知道。還有一個(gè)小習(xí)慣值得說一下每次接入新的界面框架我都會(huì)先在空工程里跑一遍它的 Demo把所有頁面點(diǎn)一遍重點(diǎn)看深色皮膚下的對比度和禁用態(tài)。原因很簡單這些地方最容易藏問題而在自身工程里樣式問題會(huì)被業(yè)務(wù)邏輯掩蓋很難判斷到底是框架的問題還是你寫錯(cuò)了。從那以后我每次往項(xiàng)目里引 UI 框架都強(qiáng)制先走一遍這套空工程驗(yàn)證再動(dòng)業(yè)務(wù)代碼。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
欧美黄业| 婷婷10月天青娱乐| 天天天堂影视日韩亚洲91| 日日夜夜摸| 福利在线观看一区二区| 精国久久一区二区三区98| 日韩成人高清一区二区| 色综合久| 麻豆天美传媒毛片| 久久女人视频| 亚洲男人天堂手机版| 91干熟女| 日日躁夜夜躁狠狠躁超爽| 日韩一区二区三区四区五区| 污电影在线观看| 人人操人人操人人操人人操人人操人人人11.CM | 99综合网| 26uuu成人影片| 91久久18禁| 日本高清有码网址视频| 亚洲熟女诱惑| 东北操逼| 久久午夜伦| 亚洲国产精品无码AV久久| 二色av| 超碰吊日色| 中文字幕二区日韩天堂| 久久二| 韩国一区二区精品亚洲| 国产操操日韩三级黄| 日韩BBN| 少妇超碰在线| 亚洲av噜噜噜噜噜噜| 午夜久久久| 吻戏激情性巴克| 日韩av在线精品观看| 吉川爱美亚洲二区在线| 日本污ww视频网站| 天天上日日上日韩精品| 加勒比性爱成人在线| 岛国色情视频在线观看| 婷婷伊人网| 91c色| 一区二区免费电影久久| 无码人妻一区二区三区免费九色| 欧美色就是色| www.亚洲黄色| 囯产精品一区二区三区线|亚洲人成无码网WWW动漫|国产精品免费一级... | 日操粉逼逼| 亚欧韩av| 亚洲精品骚逼| 99啪| 97任你吞精| 亚洲综合贴图91| 五月婷网站| 欧美亚洲| 91美女在线| 9美女超碰在线免费观看| 操碰97| 再深点灬舒服灬太大了添视频| 国产午夜精品一区二区三区牛牛| 日本高清熟女久久一区| 欧美精品偷拍| 1024香蕉视频| 久久久无码国精品无码三区三区| 婷婷色一区| 操99| 爆操无码| 欧美性爱五月天| 丁香六月婷婷| 久久人妻办公室视频| 五月婷婷六月天| 天天综合色电影| 3571色综合一区二区二区| 日本91白丝| 国产福利第一视频| 色综合美国| 欧洲亚洲人妻无码中字久久三区四区| 超碰人妻中文在线| 老熟妇一区二区三区啪啪| 欧美专利1区2区3区4区5区免费| 欧美亚洲丝袜美女电影| 欧洲亚洲人人爽爽视频| 日本精品五区| 国产乱伦性爱区| 国产精品无码论坛| 日本福利社| 日韩99神马视频播放| 久久综合久色欧美综合狠狠 | 天天操夜夜操狠很操| 手机在线A片| 91足交| 色五月激情网| 麻豆视频test| 91亚洲影院综合| 婷婷五月天福利| 麻豆伊人网| a人片中文字幕一区二区| 日韩无码第3页| 日韩强奸av| 日韩精品在线观看观看| 天堂日本亚洲欧美| 999999精品| 91粉嫩萝控精品福利网站_精品影音先锋国| 99视频内射三四| 91人妻爽爽人人做人人澡| 蜜色网色哟哟| 九九九热精品| 色色网91| 色五91| 超碰久在线天天做| 亚洲欧洲无码bt精品合集| 涩涩五月天| 精品无人区麻豆乱码1区2区图片| 性无码专区2020| 色噜噜人妻av 中文字幕| 神马久久啊啊| A 天堂| 91蜜臀熟女| 亚洲综合草草| 免费啪啪啪网站18岁| 97爱亚洲综合色| 草草草视频在线免费看| 国产日本熟女顶级一区二区三区视频| 大香蕉伊在线久草麻豆天堂故事| 97视频免费| 日本高清有码网址视频| 91麻豆天美传媒HD| 少妇久久久久久久久| 日韩精品一区的| 亚洲成人色情五月天丁香花| 欧美日韩在线国产在线| 国产精品久久久蜜臀| 97免费视频在线| 色综合一区二区三巨| 亚洲日产专区婷婷| 亚洲精品精品一区二区| 日本黄色XXX| αⅴ天堂| 久久亚洲熟妇在线视频| 波多野结衣被操50分钟免费视频| 九九九精品色乱九九九| 亚洲av淫乱| 91亚州| 99久久综合| 中文字幕一区二区三区视频播放| 91精品91久久久久77777俄罗斯老妇姓x| 久久久亚洲精品电影免费看| 吖在线不卡一区二区国产剧情| 夜夜夜夜爽| 丁香五月天堂| www.亚洲黄色| 青青草久久| 黄页视频网站野外| 国产精品懂色tv影视免费观看| 麻豆国产第一| 欧美成人亚洲精品| 久久精品国产精品亚洲艾通辽熟妇 | 亚洲 欧美综合| 色999偷自拍拍| 日本人妻A片成人免费看片| 国产二区三区免费视频| 日韩精品人妻一区二区| 天堂综合| 人人超碰在线观看黄| 九九热免费国产视频婷婷伊人| 99国产在线 精品 视频| www.亚洲成人一区| 亚洲天堂男| 欧美在线|亚洲| 综合97亚洲| 伊人一区二区三区| 国产久久久9999| 日韩国语字幕| 99久久com免费视频′| 少妇综合网| 91性情| 久久综合久色欧美综合狠狠 | 色婷五月| 五月丁香激情综合网| 国产操逼视频在线观看| 伊人久久综合影院精品久久久| 亚洲欧美另类小说| 人妻另类 专区 欧美 制服| 欧美色图片色哟哟| 无人区高清电影免费观看一区二区三 www.qmcai2.com | 日韩精品怡红院| 九九久久一区二区三区| 99www.bibizy香蕉资源国产一区二区三区高清 | 欧美日韩一二三| 亚洲色图片区| 久九九九| 色综合加勒比| 成人av影院在线观看| 精品久久久久av影院| 亚洲av无码成电影在线播放| 天天做日日做天天欢。| 天天操天天干一区二区 | 中文字幕88av在线| 神马九九九| 欧美综合传媒| 国产高清亚洲日韩一区| 老司机深夜18禁污污网站| 国产精品精品系列在线观看| 国产精品久久久久久片| 日日狠狠久久偷偷色综合免费| 亚洲人在线成线成人| 一区二区蜜臀| 亚洲天堂男人的天堂| 国产毛片片精品天天看视频| 中文字幕一二区二三区人妻专区| 手机在线视频国内精品| 91人妻尻屄视频| 亚洲射综合网| 久草精品一区 | 国产九区| 久久久久久综合久久伊人蜜月| 激情小说图片亚洲首页| 亚洲一区二区性爱电影| 九九成人| 和协无码影院| AV一二区| 性高潮久久久| 日韩激情毛片一级久久久| 大香蕉伊然在亚洲91| 亚洲少妇在线影音| 久久综合九九| 91久操| 丁香六月激情| 亚洲精品一区中文字幕乱码| 无码丰满熟妇一区二区浪潮AV| 欧美成人AⅤ大片在线观看| 色婷婷在线视频| 97超碰中文字幕| 色翁荡息又大又硬又粗又爽| 99热久| 欧美天天综合站| 最新无码国产| 6080yy午夜理论三级一区二区三区无码| 日韩人妻精品中文字幕| 亚洲激情在线观看一区| 国产熟妇一区二区| 欧美日韩性爱电影在线| 精品美女在线视频| 国产无码精品成人| 久久一二三四五六七八九区区| 欧美96精品在线| 手机看片1024你懂的国产| 亚洲。天堂。日本在线观看| 亚欧高清v| 五月天亚洲网| 日韩精品资源专区二区| 日韩激情中文字幕有码| 久草草一二三四区久久| 狠狠色噜噜狠狠狠狠狠色综合久久 | 久久草草欧美精品| 9久在线视频只有精品| 色狠狠综合噜一二三区| 美女视频尤物网在线看| 久久一本大香蕉 | 国产污视频麻豆传媒一区二区| 亚洲欧美高清无码| 蜜桃视频一区二区三区| 精品久久久高清无码| 大鸡巴久久| 日韩av三四区| 免费看欧美美女黄色大片| 97久久超碰日韩精品| 人妻22p| 国产成人亚洲精品无码最新在线| 九九亚洲精品| 啊灬啊灬啊灬好深灬快高潮了动漫-国产字幕国产在线观看-B049AV | 涩涩久久精品| 91蜜桃婷婷狠狠久久综合9色| 国产色产精品在线观看| 影音先锋一区二区在线资源| 精品v日韩欧美国产| 免费人成毛片乱码| 加勒比五月天| 超碰亚洲97| 久久久久亚洲三级电影| 亚洲男人电影天堂| 加勒比久久av| 久久一留热品黄| 天天爽夜夜操| 91丨熟女丨丰满熟女| 97久久精品| 蜜臀Av一区二区三区| surenchaopeng| 欧美大香蕉卡久久| 蜜乳性色无码专日粉嫩骚逼AV| 日韩无码第3页| 狠狠色五月亚洲91| 99re6国产精品99re| 96AV久久久| 婷婷激情啪啪| 高清在线偷拍自拍视频| 久久夜黄色无码A级大片| 日本操逼视频不卡直接放| 蜜臀99久久国产| 美女t无毒不卡不卡| 九九人妻| 亚洲性高潮| 成人AV素股で擦久久| 欧美淫穴| 97色色国产视频| 久草精品国产蜜臀| 欧洲精品久久| 骚日日av| 操碰97| 加勒比99999| 久久久久久久久999| 久久免费少妇| 亚洲成a人v欧美综合天堂下载| 精品无码久久久久久久久果冻糖心| 91精品人妻一区二区三区蜜桃| 欧美色网络| 葡萄牙性视频一二区| 青青青青青手机视频| 亚洲国产综合图区中文字幕 | 99久久网站| 青青欧美在线| 很黄很色的视频在线观看| 国产 亚洲 一二三四| 国产夜夜艹| 蜜臀久久99精品久久久电影| 中文字幕在线免费观看2| 超碰欧美| 中文激情网| 有码专区最新中文字幕有码| 亚洲成人美女无吗| 天天干人人看综合| 超碰超碰超碰超碰的大鸡吧操黑丝袜| 清纯唯美第一页| 在线视频 亚洲精品| 无遮挡一级毛片视频免费的| 熟女乱伦A| 丁香五月婷婷基地| 女色视频社区| 久草在| 亚洲第一页综合在线| 2024年最新色情网站在线观看| heyZO天然素人无码AⅤ专区| 色官网色综合| 久超碰在| 久久是精品| 亚洲91网| 激情抓乳插进去啪啪啪日韩 | 97玖玖人妻| 国产精品久久久午夜夜伦鲁鲁| 26uuu最新| 色色五月天激情| 欧美天天在线| 91人妻人人澡人人爽人人精品| 最近2019中文字幕国语免费版| 91夜夜蜜桃臀1区2区3区| 999999精品| 丝袜无码a片| 大香蕉免费中文| 亚洲精品一区二区免费在线观看| 欧美高潮| 欧美日韩性爱操大逼| 激情四射婷婷六月天| 国产精品高潮呻吟av久久4虎| 人人爱人人操人人性| 天美传媒Av在线| 日本中文熟女视频| 欧美精品第四五页中文字幕在线观看| 97视频在线播放| 99热精品免费| 亚洲男人的天堂va亚洲男人社| 亚洲激情久久| 美女黄码视频午夜| 精品欧美老熟女一二区| 极品丝袜无码| 欧美日韩午夜精品一区二区三区| 麻豆AV96熟妇人妻| 综合影视国产无码| 激情视频一二三| 18禁无码永久免费无限制| 无码人妻丰满熟妇奶水区毛片| 午夜福利一区二区影院| 韩国三级三级BD在线| 欧美性爱第一区| 超碰69| 天堂中文日本在线观看| 久久99国产精品| 91精品成人| 无码日韩网站| 无遮挡男女激烈动态图| 欧美曰韩国产精品| 久久久精品视频免费观看| 超碰人人干天天射| 精品免费1| 精品国产久热在线观看| 人人操人人舒服| 女上位精品在线| 欧美大香蕉卡久久| 亚洲啪啪性视频| 亚洲无码太久| 亚洲欧美综合图片| 精久久久91| 亚州免费啪啪视频| 天天综合-91入口| 婷婷精品国产欧美精品亚洲人人爽| 婷婷色导航| 草草草视频在线免费看| 亚洲日本天堂| 精品成人女人久久| 久久国模av| 久久色激情一区二区三区| 九九久久综合| 免費黃色視頻觀看一| 欧美成人AⅤ大片在线观看| 九九热久久99精品re| 欧美日韩色| 亚洲激情欧美色图 | 国产偷人伦激情在线观看| 久久精品中文| 91久久国外网| 中亚黄色三级大片| 中文一区二区| 亚洲高潮影院| 后入精品| 日韩黄色小说| 97超碰免费人人性爱| 久久夜嗨| 日日嗨AV一区二区夜夜| 大香蕉欧美日韩| 99热 按摩 日韩| 91性| 午夜精品久久久久久久久久久久久 | 亚洲毛片基地专区| 人妻人人澡人人爽人人| 超碰在线在公开超碰在线在公开| 91丝袜| 可以在线观看的黄色网址| 一区二区三区四区色图| 97伦综合| 国产白嫩漂亮KTV在线| 国产兽交视频在线播放| av在线观看不卡网站| 成人开心网在线视频| 伊人一区二区三区| 被操高清无码视频| 东京太热男人的天堂久久久| 偷拍亚洲情色| 乱欲视频| 欧亚性爱啪啪| 亚洲最大黄网| 欧美色图 人妻| 亚洲欧美校园| 在线综合 亚洲 欧美中文字幕| 欧日韩一二三f区| 日韩精品三级| a啊啊啊啊啊啊啊啊一区二区| 天天插网| 99免费在线视频| 青青草久久一区网| 噜噜瑟| 人人妻碰人人免费| 温婉少妇玩3p| 内射黑人| 少妇久久久久久| 日逼视频日本| 伊人97超碰| 免费草草草草草视频| 免费αV在线视频| 久久免费老司机精品| 综合亚洲网| 日天天九九天堂666| av绯色| 欧美日韩成人在线| 久偷拍欧美日韩三区| 九月伊人中文字幕| 丁香六月婷婷| 国产中文字幕在线观看| 国产亚洲深夜激情| 青青草啪啪网| 日韩免费看在线黄色片| 久久精品三级影视| 爱丝福利| 国产小黄片在线免费观看| 久久草视频污视频| 男人的天堂视频精品乱在线| 五月天综合在线| 成人性生活高清视频在线播放| 伊人五月天激情| 美女天天干| 无码 有码 国产18p| 91老熟女91老女人| 国产女性无套 免费观看| 91精品导航| 婷婷五月天激情网| 日韩欧美~中文字| 超碰人人乐97| 9丨亚洲一区二区在线| 一区二区三区四区五区高清无码永久视频| 91国精产品| 国产激情av女片自拍| 91插B网站| 亚洲s在线观看| 女性喷水高潮在线观看| 8050无码八戒| 97色网| 黑丝少妇在线观看| 好色综合| 亚洲综合69| 丁香五月天堂网| 亚洲图片欧美色图| 麻豆人妻少妇在线免费观看| 搡老女人老熟女91| KK色在线影院| 91国产大片| 五月丁香社区婷婷日韩欧美精品影院 | 精品久| 91精品又粗又猛又爽| 九九碰九九爱97| 女性喷水高潮在线观看| 3级毛片一二| 亚洲人成色9999精品久久| 屁屁影院一区二区三区国产 | 日韩国产精品人妻无码久久久| 国产白丝在线| 好爽,再快点啊哈嗯嗯嗯嗯| 亚洲欧美国产日本一区二区三区| 懂色中文一区二区三区 | 亚洲色图日韩精品| 国产强奸乱伦欧美| 67914在线兔费成人视频| 区一二区日韩亚洲乱码av电影| 97色婷| 热九九精品| 日本护士高潮| 草莓精品视频在线免费观看| 成人精品在线免费视频| 欧美综合色综合| 91超级碰碰碰| 精品一区二区综合熟妇| 欧美精品99久久久**| 97超碰人人模人人拍人人| 亚州性9| 69久久| 夜夜影视四色| 91东京热男人的天堂| 久久久久久九九九九| 中文字幕十五区| 91老熟女逼| 91精品人妻一区二区-全集完整版免费正片国语-B02AV | 青青草好吊色| 午夜在线播放| 久久久亚洲| 日本欧美中文字幕| 欧美天天综| 精品熟女一区=区三区| 九九九九AV| 久久久专区| 国产家庭乱伦网址| 亚洲不卡不卡中文字幕不卡 | 久热伊人| 久久一区,青青青青草视频在线播放| 国产精品网站免费| 久久少妇人妻| 女人香蕉久久毛毛片精品| 九九Av| 亚州伊人色综台| 久久九九一区二区三区成人| 校园春色美腿丝袜| 精品黄色电影| 精品国产丝袜一区二区三区乱码 | 国产精品久久久午夜夜伦鲁鲁| 色九月综合| 久久男人网| 热热色综合网| 亚洲成人免费中文字幕| 噜噜吧,噜噜色,噜噜| 日韩中文字幕二区| 国产精品青青草| 好舒服视频| 色欲av国内精品久久久久久| 亚洲最新av无码成人精品区| 九九aV| 欧美拳交在线播放| 老熟女中文字幕高清| 啊啊啊啊啊啊在线| 国产亚洲禁久一区二区| 狠插 制服 自拍| 人妻无码一区二区三区久久99| 亚洲国产精品无石码久久| 国产精品无码久久久久2025| 中文字幕 一区二区 亚洲无码| 激情综合 婷婷五月 红杏| A级毛片在线看免费| 婷婷丁香六月| 大奶的诱惑| 欧美日本国产日韩激情视频| 欧美日韩夜夜| 精品在线蜜臀| 欧美日韩日产免费网站看| 成人性爱电影一区二区| 亚洲AV人人澡人人爱| 色综合av男人天堂| 丝袜剧情| 欧美天天谢综合网| 日本高清免费一本视频在线观看| xxx亚洲午夜天堂| 欧美色图校园春色| 色香色香欲天天天影视综合网| 少妇高潮喷水无套久久久久久| 伊人久操| 啊啊啊轻点在线观看| 乱伦Av网| 日本性一区| AA丁香综合激情| 加勒比伊人综合| 国产辣妈在线视频福利| www四虎| 69少妇一区二区| 大香蕉综合在线| 97天堂| 91亚洲欧洲| xxx亚洲午夜天堂| 狠狠色噜噜狠狠狠狠2018| 开心五月婷婷| 国产精品永久免费10000| 大香蕉宅男伊人| www.大香| 欧美96在线|欧| 欧美精品久久96人妻无码| 精品人妻中文字幕4399| 色香91| 天天综合网~69| 亚洲精品成人动漫在线| 全国男人天堂网| 青青草伊人久久| com 首页 18岁 禁区 女优 免费 精选 同城| 国产尹人在线视频免费| 98人妻精品一区二区色欲| 日韩日韩日韩-国产乱码精品一区二区| 91xingse| 婷婷久久网| 欧美十八禁导航成人| 精品人妻丰满熟妇一区二区三| 夜夜福利| 天天做天天爽| 人人射人人操人人摸| 操人人| 国产女大学生AV| 亚春色色| 精品久久久不卡一区二区| 四虎 精品 WWW| 久久久免费一级黄片| 一区二区三区亚洲| 2024黄色视频| 国产sv美女内射| 国产精品一区二区后入| 亚洲色人妻综合| 久久五月份| 国产成人无码久久精品| 91成人高清在线观看| 一级毛片电影免费看| 日韩福利电影网| 久热这里只有精品9| 日本黄色精品| 国产高清成人免费视频| 江都AV在线| 日本日皮视频逼| 无码高清专| 911粉嫩人妻| 久久东京国产精品视频| 欧美综合777| 噜噜噜亚洲精品| 一区二区首页| 香蕉大久久久| 国产中文字幕在线观看| 激情欧美97| 97人妻人人躁人人玩人人| 五月天欧美色图| 久久精品免视看国产成人﹣蜜臀av一区. 久久精品免视看国产成人,蜜臀av一区 | 国产精品在线网站| 日逼五月天| 91精品操美女| 久久欧美激情| 玖玖色综合| 91欧美偷拍| 蜜乳AV色欲AVAV无码| 另类欧美色| 亚洲AV噜噜狠狠网址蜜桃动漫| 色 亚洲 91| 欧美最婬乱婬爆婬性视频| 欧美色图片91| 午夜视频久久久| 男人女人18禁片免费看网站| AV不卡在线| 99欧美| 色女99一级片在线观看| 无码视频一区二区| 欧美日韩亚洲国产中文永久天天看| 欧美72网页| 久久久啊啊啊| 伊人色综合欧美| 天天舔天天日天天射| 久久大香蕉97| 美女午夜福利免费视频| 国产一级片| 欧美亚洲厕所精品偷拍91| 精品高潮| 中文字幕av乱伦| 欧美亚洲第1页| sewuyueav| 日韩国产中文字幕| 夜夜狠狠躁日日躁色视频| 亚洲蜜臀精品视频久久| 欧美少妇色图| 亚洲激情网一二三四区| 国产精品久久久午夜夜伦鲁鲁| 国产特级毛片AAAAAA高潮流水| 久久精彩视频| 国产超碰欧美| 国产精品视频一区二区三区八戒| 日本一区二区三区精品| 夜夜躁狠狠躁日日躁av| 亚洲色偷偷色噜噜狠狠99网| 极品人妻少妇综合| 欧美自拍偷拍免费观看| 9久精品视频在线观看| 国产无马视频| 午夜呻吟欧美| 国产福利合集| 福利偷拍视频-中文字幕2019国语完整视频大全-S91AV | 夜草网站| 日本 免费 一区二区三区 久久香蕉| 欧洲亚洲少妇| 天天舔天天 | 欧美日韩m| 欧美性夜| 亚洲麻豆av一区二区| 激情抓乳插进去啪啪啪日韩 | 香港日本韩国人妇99www.wccm20| av在线观看不卡网站| 久久伊人青青草| av无码av无码专区| 久久超碰天天| 少妇蜜汁| 乱伦a片视频| 易易A毛视频| 亚洲精品天天影视综合网| 韩国一级AAA| 蜜臀99久久精品久久久久久| 无码国产精品午夜不卡(| 超碰97久久| 精品人妻一区春色| 亚洲色图91欧美日韩| 插穴性爱视频在线观看| 国产suv精品一区| 色九月婷婷| 欧美一区二区三区互相| 国产精品电影推荐| 极品色www影院| 亚洲精品国语在线播放| 欧美 日韩第一性色| 成人熟女视频一区二区三区| 久久成人午夜精品影院 | 青青操狠狠撩| 中文字幕二区日韩天堂| 国产福利影视| 最新中文字幕精品在线| 69精品| 久久久偷拍| 97视频7| 天天射影院| 射丝袜大香蕉| laoshunv91| 97超碰色色| 久草色在线观看| 日韩av情韩国爱禁区av一区二区| 求求你操操我| 色呦呦、国产精品| 91GD.COM| 久久久久久AⅤ无码免费肉站 | 碰超人人在线一区二区三区| 熟啊v色欧美热| 欧美亚男人的天堂| 日韩情色视频| 少妇免费视频| 99re在线观看| 久久久成人免费av电影| 中国小夫妻勾搭露脸淫荡对白| 香蕉99秘 精品一区丁香| 色综合久久888| 欧美日韩精品一区二区三区高清| 国产天美传媒精品| 逼操网站| 无遮挡猛进视频免费无限观看| www久| 国产夫妻一区二区| 极品色www影院| 九色 人妻 大香蕉| 日韩二级| 天天拍天| 久久久精精精| 中文字幕美女91| 欧美色涩| 国产乱色国产精品免费视| 欧美啪啪啪91| 韩国三级一线观看久| 黑人精品成人一区二区三区| 天天干人妇| 98一区二区精品| A男人的天堂| 欧美写真视频一区| 日本不卡高清视频| 狠狠操狠狠插| 国产亚洲精品美女久久久| 国产午夜激片Av毛片不卡| 天天欧美色| 亚洲综合一| 色婷婷六月丁香七月婷婷| 久久久久国产精品片区无码直播| 日韩精品在线观看网站| 久婷婷一区| 亚洲日韩国产精品| 日本高清一区二区在线| 超碰人人妻| 欧美偷偷网| 无码精品久久| 久久婷婷一区二| 性欧美999| 黄色一区二区秘书性感| AAA久久| 动漫片子网站3黄| 东京热,男人的天堂| 四虎影视永久在线免费| 亚洲国成人情色好看电影| 国产97在线 | 亚洲| 人人插人人搞人人操| 中文字幕AV片| 成人精品在线免费视频| 日本色色视频网站| 91被操| 极品粉嫩一区二区| 爱射综合| 国产家庭乱伦表演| 欧美拳交在线播放| 欧美高清性猛交| 九九九九九九成人| 日韩成人网址| 丁香五月天社区| 欧亚揄拍偷拍精品视频| 五月天婷婷在线看| 亚洲综合有玛| 国产精品久久| 久久天天躁日日躁狠狠躁| 婷婷久久五月综合激情| 手机在线人成免费视频| 中文字幕精品三级久久久| 超碰97综合网| 亚洲图片偷拍视频区| 久久加勒比| www.婷婷五月天| 中文字幕丰满人妻日本| 人妻出轨一区二区三区| 亚洲欧美高清| 五月丁香久久| 污污汅18禁网站在线永久免费观看 | 无色无码| 欧美九九九九九| 东京成人一区| av日韩手机在线影视| 大香蕉中文在线| 精品一区二区麻豆| www.夜夜| 中文字幕一区二区韩| 中文字幕黄色一起草| 97视频在| 国产超碰人人爽人人做| 97在线看| 青青草大香蕉视频| 自拍欧美| 色色色色网站| 丁香婷婷五月| 久久久偷拍| 狠狠操狠狠燥| 亚洲日产专区婷婷| 97青娱乐超碰久久| 性色avv| 老女人爆菊| 日韩精品视频在线观看一卡二卡| 色综合av综合久久| 自拍第一页| 欧美午夜视频| 日韩免费人妻色情网站| 亚洲精品日韩国产欧美| 人人看欧美性爱| 精品国产一区二区三区四区在线看| 蜜臀AV一区二区三区| 2017天天操天天日| 自拍啪啪视频| 另类小说欧美激情校园春色| 亚洲中文字幕乱码无码一区二区| 亚洲 日韩 欧美 国产综合体| 后入人妻无码| 97超碰这里只有精品| 色综合99999| 超碰97亚洲区| 中文字幕超碰CAO| 欧美一二在线| 天天亚洲综合| 97超碰热线| 嗯,啊。舔我逼| 国产精选视频| 97久久久| 一级aaaaa欧美中文字幕录像片| 欧美日韩性爱无码| 大香蕉久操| 色综合色欲色综合色综合色综合| A片三级无码| 91N欧美| 99re69| 欧美伦乱爱| 天天夜夜rb| 亚洲欧美高清无码| 91精品无码久久久久久久| 正宗无毛一线天嫩逼| 亚洲欧美啪啪| 高清国产精品福利网站| 国产精品嫩草影院免费| 色色色综合| 日韩不卡网操逼中文字幕日韩| 夫妻AV网站| 国产大陆天天艹| 亚洲另类在线观看| 亚洲视频一二区| 97香蕉网| 偷拍 欧美 日韩| 国产精品青草综合久久| 日本东京热大香蕉a片| 久夜操| 在线国产福利网址导航| 狠狠激情综合狠狠操中文字幕| 欧美高清性猛交| 美女诱惑一区| 日日操天天操| 欧美在线|亚洲| 久久9久| 国产女人高潮视频| 亚洲玖玖爱| 家庭乱伦性爱av| 女人爽到高潮久久久| 女人一区| AAAA欧美日韩| 欧亚乱色熟一区二区三四区| 青青草在线视频播放器| 操操逼操操逼操操逼逼| 夜夜夜夜夜夜夜夜夜狠狠狠狠狠狠狠| 国产AV线| 国产在线精品偷| 日本精品一区二区三| 一级人妻性爱视频| 精品久久99| 日本东京热久久久电影| 日韩亚洲美州欧洲综三区一品在线| 久久久久9999妇女| 国产一区二区三区白丝| 中文字日本乱码| 极品欧美一区二区三区| 97天天综合网| 天美传媒婬乱在| 欧美大香蕉在线观看| 国产一区二区三区高清视频| 精品免费1| 免费一级性爱久久| 日本天堂在线播放| 亚洲囯产精品女人久久久| 吊色| 嗯嗯嗯好爽| 黄色免费一级在线毛片| 人妻酒店出差被中出免费在线播放| 26uuu久久| 中文欧丝袜诱惑| a级理论午夜日本| 一区二区乱码福利| 天天操天天日青青草超碰av| 自拍鲍鱼一区在线高清观看免费| 超碰超碰超碰超碰的大鸡吧操黑丝袜 | 国内成人圈中文字幕无码视频| 人人 操人人 操人人| 青青草国产一区二区三区| 大奶啊啊好爽| 欧美极品性爱天天射| 亚洲在线欧美| 999 久久久| 天天爽天天操| 日欧亚洲二三区大片不卡| 一区二区影视| 人人澡人人澡人人| 欧美日本久久精品一区 | 一本久久精品中文字| 色婷婷久久| www.久久制服糖| 超碰97伊人| 99精品久久久久久| 亚洲永久永久永久永久一级一级一级精品 | 日韩操逼性鲍| 亚洲国产综合图区中文字幕| 久久99999| 亚洲欧美爆| 久久黄色网址| 97任你吞精| 免费在线黄片视频| 最新三级网址| 十八禁av无码免费网站APP| 中文字幕一区二区三区50路| 亚洲精品国产av天美传媒| 精品人妻一区二区三区-国产精品| 天天操综合网| 欧美日韩国产色图在线| 秋霞成人一级在线观看| 男女猛烈无遮掩视频免费软件| 好吊色综合| 久久97超碰| 久久免费少妇| 欧美影院一区二区三区| 欧美成熟性爱精品| 1769国内精品视频| 色就色综合| 欧美色性爱| 欧美日韩成人| 青青操青娱乐| 在线黄色污污网站| 天天天天做夜夜夜夜做| 精品人妻无码一区二区三区不卡-精品人妻无码一区二区...|精品少妇一区二区三 | 91春色| 天天上日日上日韩精品| 美女诱惑一区| 自拍大香蕉乱插| 少妇的嫩逼图片| 色99在线| 色欲日韩欧美在线一区| 国产日韩手机视频在线| 精品免费视频国产一区| 一二三区操逼国产91| 亚洲成人久久美女| 丰满人妻-区二区三区免费| 久久久网站| 不卡啪啪视频| 狠狠久久亚洲欧美专区| 久久ww| 亚洲男人天堂2019| 亚洲无码色| 天天插天天操| 日产操逼| 日曰骚久久精品| 亚洲色图 欧美| 亚洲欧美综合区自拍另类| 一级乱伦网站| {男男暴菊gay无套网站| αⅴ天堂| 丁香五月色情| 欧美伦乱爱| 0755午夜福利视频| juliaann欧美丝袜办公室| 神马久久久久久久久| 曰本道人妻久久久在线不卡色视频| av草草在线电影| 99蜜桃臀久久久欧美精品网站| 区一在线观看| 青青草日韩免费观看高清在线| 啊啊啊慢点| 乱伦av麻豆| AV99热18这里只有精品| 国内毛片热久久思思热| 丁香五月自拍| 99精品综合久久久久五月天| 日韩亚洲国产视频| 夜夜嗨绯色| 国产精品久久久| 国产精品一区人妻精品阁在线| 凹凸 69堂 在线播放| 亚洲日韩美国人妻| laoshunv91| 日日噜噜夜夜狠狠视频无| 99九九久久| 久久人人舔人人爽舔人人av片| 欧美伦乱爱| 国产强奸乱伦无码视频| 一本正道久久熟女| 日韩av在线精品观看| 五月天色电影| 久久久久久精| 久草男人天堂| 婷婷五月天激情网| 欧美色亚洲色| 97在线欧洲| 中文?日韩?免费?精品| 久久鲁夜| 欧美东京热精品A∨| 99re这里| 韩日精品四区| 国产偷拍网站| 国产AV天美传媒一区二区三区 | 丰满少妇一区二区三区免费看| 九九九九久久久| 亚洲国产一级黄色视频| 久久久成人免费av电影| 伊人网综合在线视频| 亚洲情色 自拍| 欧美狠狠鲁| 岛国成人av在线播放网址| 淫荡网址| 欧美色91| 麻豆久久久久久久久丝袜| 无色无码| 韩国成人精品久久久免费看| 97在线欧| 欧美久久婷婷| 久操网址| 91痴汉| 在线观看视频91| 97久精品| 人人艹亚洲| 综合伊人网12色| 日少妇视频| 亚洲天堂男| 国产超碰97| 学生妹天天看| 欧美色图亚州激情| 色妹子A V| 激情综合二| 欧美性爱第一页久久| 少妇淫妇久久久久久久| 激情综合网一盗摄| 91 手机在线播放 绯色| 欧美在线播放aaaa| 走光一区92下载| 成人精品久久| 久久久久人| 99热这里只有精品8| 国模吧 一区二区三区| 蜜臀操逼黄色视频操的好爽| 欧美双插| 永久免费观看的毛片的网站| 超碰97玖玖爱| 18岁禁 茉莉成人久久| 欧美 亚洲 大香| 欧美色日| 亚洲97网站| 高清无码91| Julia Annxxxxx| 玖玖综合视频| 9Ⅰ超碰| 一区二区高清视频| 懂色中文一区二区三区| 人人妻人射| 97综合国产| 日韩免费看在线黄色片| 国产操操日韩三级黄| 亚洲色五月| 午夜天天碰综合视频| 精品人妻视频一区二区三区蜜桃视频|