最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

c# WPF中如何自定義MarkupExtension

 更新時(shí)間:2021年03月01日 15:20:59   作者:Hello——尋夢(mèng)者!  
這篇文章主要介紹了c# WPF中如何自定義MarkupExtension,幫助大家更好的理解和學(xué)習(xí)使用c# wpf,感興趣的朋友可以了解下

  在介紹這一篇文章之前,我們首先來(lái)回顧一下WPF中的一些基礎(chǔ)的概念,首先當(dāng)然是XAML了,XAML全稱是Extensible Application Markup Language (可擴(kuò)展應(yīng)用程序標(biāo)記語(yǔ)言),是專門(mén)用于WPF技術(shù)中的UI設(shè)計(jì)語(yǔ)言,通過(guò)使用XAML語(yǔ)言,我們能夠快速設(shè)計(jì)軟件界面,同時(shí)能夠通過(guò)綁定這種機(jī)制能夠很好地實(shí)現(xiàn)界面和實(shí)現(xiàn)邏輯之間的解耦,這個(gè)就是MVVM模式的核心了,那么今天我們介紹的MarkupExtension和XAML之間又有哪些的關(guān)系呢?  

  Markup Extension,顧名思義,就是對(duì)xaml的擴(kuò)展,在XAML中,規(guī)定如果屬性以{}開(kāi)始及結(jié)束,就是Markup Extension,Markup Extension指的是繼承于MarkupExtension的類,首先我們通過(guò)一張圖來(lái)看看WPF中有哪些已知的Markup Extension。

  看了這張圖片之后是不是對(duì)這個(gè)MarkupExtension有一個(gè)常規(guī)的認(rèn)識(shí),你會(huì)發(fā)現(xiàn)這個(gè)在WPF中實(shí)在是太重要了,通過(guò)這個(gè)MarkupExtension我們能夠?qū)崿F(xiàn)綁定、資源等等一系列的操作,在介紹完這個(gè)之后,我們來(lái)看看,這個(gè)抽象的MarkupExtension基類到底是什么?里面包含些什么?怎么去使用它?

#region 程序集 WindowsBase.dll, v3.0.0.0
// C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\WindowsBase.dll
#endregion

using System;

namespace System.Windows.Markup
{
 // 摘要:
 //  為所有 XAML 標(biāo)記擴(kuò)展提供基類。
 public abstract class MarkupExtension
 {
  // 摘要:
  //  初始化從 System.Windows.Markup.MarkupExtension 派生的類的新實(shí)例。
  protected MarkupExtension();

  // 摘要:
  //  在派生類中實(shí)現(xiàn)時(shí),返回一個(gè)對(duì)象,此對(duì)象被設(shè)置為此標(biāo)記擴(kuò)展的目標(biāo)屬性的值。
  //
  // 參數(shù):
  // serviceProvider:
  //  可以為標(biāo)記擴(kuò)展提供服務(wù)的對(duì)象。
  //
  // 返回結(jié)果:
  //  將在擴(kuò)展應(yīng)用到的屬性上設(shè)置的對(duì)象值。
  public abstract object ProvideValue(IServiceProvider serviceProvider);
 }
}

   其實(shí)看看里面的內(nèi)容,僅僅提供了一個(gè)抽象的方法ProvideValue,我們?cè)诶^承這個(gè)抽象類后需要去重載這個(gè)抽象方法,然后來(lái)實(shí)現(xiàn)自己的邏輯。

  在對(duì)整個(gè)MarkupExtension介紹之后,我們可以對(duì)它進(jìn)行一個(gè)總結(jié),那就是:

  XAML標(biāo)記擴(kuò)展語(yǔ)法格式:

  <元素對(duì)象 對(duì)象屬性=”{擴(kuò)展標(biāo)記 擴(kuò)展標(biāo)記屬性 = 擴(kuò)展屬性值}” />
      這個(gè)是不是很熟悉,如果還是不夠直觀的話,我們可以通過(guò)代碼來(lái)進(jìn)行說(shuō)明:      

<TextBox Text=”{Binding Path=ProductName}”/>

  再來(lái)一個(gè)復(fù)雜一些的例子吧

<Popup IsOpen="{Binding Path=IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" Placement="Right" x:Name="SubMenuPopup" Focusable="false" AllowsTransparency="true" PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}"/>

  類似的這種我們?cè)赪PF中見(jiàn)到的是在是太多了,那么既然基類是一個(gè)抽象方法那么我們是不是可以通過(guò)重載這種方式來(lái)寫(xiě)自己的MarkupExtension呢?這個(gè)當(dāng)然是可以的,我們可以通過(guò)下面的幾個(gè)例子來(lái)進(jìn)行相應(yīng)的說(shuō)明。

  示例1:通過(guò)MarkupExtension綁定MenuItem的Icon屬性。

  我們知道,MenuItem的Icon屬性可以通過(guò)下面的方式進(jìn)行設(shè)置:

<MenuItem Header="New">
  <MenuItem.Icon>
    <Image Source="data/cat.png"/>
  </MenuItem.Icon>
</MenuItem>

  這個(gè)是MSDN介紹的常規(guī)方式,在這里我們可以通過(guò)三種不同的方式來(lái)達(dá)到這個(gè)目的,具體來(lái)看看是怎么實(shí)現(xiàn)的吧?

<Menu Grid.Column="0">
           <MenuItem Header="文本">
               <MenuItem Header="重做">
                   <MenuItem.Icon>
                       <Image Stretch="Uniform" Source="{extension:ImageBinding Redo}"></Image>
                   </MenuItem.Icon>
               </MenuItem>
               <MenuItem Header="撤銷">
                   <MenuItem.Icon>
                       <Image Stretch="Uniform" Source="{extension:ImageBinding Undo}"></Image>
                   </MenuItem.Icon>
               </MenuItem>
               <MenuItem Header="保存所有">
                   <MenuItem.Icon>
                       <Image Stretch="Uniform" Source="{Binding SaveAll,Converter={StaticResource SourceConverter}}"></Image>
                   </MenuItem.Icon>
               </MenuItem>
               <MenuItem Header="測(cè)試">
                   <MenuItem.Icon>
                       <Image Stretch="Uniform" Source="Resources/Images/Redo.png"></Image>
                   </MenuItem.Icon>
               </MenuItem>
           </MenuItem>
           <MenuItem Header="編輯"></MenuItem>
           <MenuItem Header="視圖"></MenuItem>
           <MenuItem Header="插件"></MenuItem>
       </Menu>

  第一種方式就是我們今天重點(diǎn)介紹的通過(guò)繼承MarkupExtension來(lái)實(shí)現(xiàn)同樣的效果,我們來(lái)具體分析一下這個(gè)ImageBinding

public class ImageBindingExtension : System.Windows.Markup.MarkupExtension
   {
       public ImageBindingExtension(string path)
           : this()
       {
           Path = path;
       }
 
       public ImageBindingExtension()
       {
       }
 
       [ConstructorArgument("path")]
       public string Path
       {
           get;
           set;
       }
 
 
       public override object ProvideValue(IServiceProvider serviceProvider)
       {
           IProvideValueTarget target = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
 
           if (target.TargetObject is Setter)
           {
               return new Binding(Path) { Converter = ImgaeSourceConverter.Default };
           }
           else
           {
               Binding binding = new Binding(Path) { Converter = ImgaeSourceConverter.Default };
               return binding.ProvideValue(serviceProvider);
           }
           
       }
   }

  這里面我們定義的Path屬性就是綁定到ViewModel中的一個(gè)特定的屬性,這里我們通過(guò)重寫(xiě)ProvideValue方法,最終調(diào)用BindingBase的ProvideValue返回ImageSource對(duì)象,這里是通過(guò)一個(gè)轉(zhuǎn)換器來(lái)實(shí)現(xiàn)源屬性(字符串)到目標(biāo)屬性ImageSource的轉(zhuǎn)換的,我們會(huì)發(fā)現(xiàn),其實(shí)這種方法和直接綁定并設(shè)置轉(zhuǎn)換器其實(shí)效果是一樣的,只不過(guò)第一種方式更為直觀,將所有的轉(zhuǎn)換過(guò)程都放在了重寫(xiě)ProvideValue函數(shù)的過(guò)程中了,這個(gè)讀者在后面可以對(duì)照demo去認(rèn)真思考然后加以總結(jié)。

  示例2:通過(guò)MarkupExtension綁定到ListBox的ItemsSource屬性

  這個(gè)稍微復(fù)雜一些,我們?cè)赗eflection這個(gè)MarkupExtension中加入了一些自定義的屬性,這些屬性能夠控制后面返回的數(shù)據(jù)源的最終內(nèi)容,其實(shí)這個(gè)也是非常好理解的,我們?cè)诙xRelativeSource這個(gè)MarkupExtension的時(shí)候,也是通過(guò)定義Mode、AncestorType、AncestorLevel等屬性組合起來(lái)最終實(shí)現(xiàn)在視覺(jué)樹(shù)上找到最終的元素。在代碼里面也不復(fù)雜主要是通過(guò)反射來(lái)獲取Button的屬性、方法、事件、字段等等,這個(gè)具體的實(shí)現(xiàn)過(guò)程可以參考后面的代碼。

public class ReflectionExtension : System.Windows.Markup.MarkupExtension
    {
        public Type CurrentType { get; set; }
        public bool IncludeMethods { get; set; }
        public bool IncludeFields { get; set; }
        public bool IncludeEvents { get; set; }
 
        public ReflectionExtension(Type currentType)
        {
            this.CurrentType = currentType;
        }
 
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            if (this.CurrentType == null)
            {
                throw new ArgumentException("Type argument is not specified");
            }
 
            ObservableCollection<string> collection = new ObservableCollection<string>();
            foreach (PropertyInfo p in this.CurrentType.GetProperties())
            {
                collection.Add(string.Format("屬性 : {0}", p.Name));
            }
 
            if (this.IncludeMethods)
            {
                foreach (MethodInfo m in this.CurrentType.GetMethods())
                {
                    collection.Add(string.Format("方法 : {0} with {1} argument(s)", m.Name, m.GetParameters().Count()));
                }
            }
            if (this.IncludeFields)
            {
                foreach (FieldInfo f in this.CurrentType.GetFields())
                {
                    collection.Add(string.Format("字段 : {0}", f.Name));
                }
            }
            if (this.IncludeEvents)
            {
                foreach (EventInfo e in this.CurrentType.GetEvents())
                {
                    collection.Add(string.Format("事件 : {0}", e.Name));
                }
            }
            return collection;
        }
 
    }

  今天就如何自定義MarkupExtension做了一個(gè)簡(jiǎn)單的介紹,最重要的是能夠通過(guò)這種方式來(lái)實(shí)現(xiàn)自己的合理綁定的目的,同時(shí)通過(guò)這種合理的擴(kuò)展方式也能夠讓我們的代碼更加靈活多變,最后附上整個(gè)測(cè)試用的DEMO,希望有需要的點(diǎn)擊進(jìn)行下載,這篇文章只是一個(gè)拋磚引玉的作用,希望讀完之后能引發(fā)自己更多的共鳴,最終代碼越寫(xiě)越好。

以上就是c# WPF中如何自定義MarkupExtension的詳細(xì)內(nèi)容,更多關(guān)于WPF中自定義MarkupExtension的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C#套接字(Socket)通信之UDP組播詳解

    C#套接字(Socket)通信之UDP組播詳解

    單播 Unicast是指客戶端與服務(wù)器之間的點(diǎn)到點(diǎn)連接,組播和單播的差別是,必須得有一個(gè)“組”的概念,然后才能進(jìn)行組播,本文就來(lái)和大家講講UDP組播的實(shí)現(xiàn)吧
    2023-05-05
  • C# 多線程中經(jīng)常訪問(wèn)同一資源可能造成哪些問(wèn)題

    C# 多線程中經(jīng)常訪問(wèn)同一資源可能造成哪些問(wèn)題

    這篇文章主要介紹了C# 多線程中經(jīng)常訪問(wèn)同一資源可能造成哪些問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • C#簡(jiǎn)單讀取主機(jī)上所有進(jìn)程的方法

    C#簡(jiǎn)單讀取主機(jī)上所有進(jìn)程的方法

    這篇文章主要介紹了C#簡(jiǎn)單讀取主機(jī)上所有進(jìn)程的方法,涉及C#進(jìn)程的遍歷讀取操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2016-08-08
  • c# winform讀取xml文件創(chuàng)建菜單的代碼

    c# winform讀取xml文件創(chuàng)建菜單的代碼

    動(dòng)態(tài)創(chuàng)建菜單使得程序靈活性大大增加,本文根據(jù)讀取xml文件中的配置菜單項(xiàng)來(lái)動(dòng)態(tài)創(chuàng)建菜單,代碼如下
    2013-09-09
  • C#讀寫(xiě)EXCEL單元格的問(wèn)題實(shí)現(xiàn)

    C#讀寫(xiě)EXCEL單元格的問(wèn)題實(shí)現(xiàn)

    這篇文章主要介紹了C#讀寫(xiě)EXCEL單元格的問(wèn)題實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-04-04
  • 解析OpenXml?Pptx的邊框虛線轉(zhuǎn)為WPF的邊框虛線問(wèn)題

    解析OpenXml?Pptx的邊框虛線轉(zhuǎn)為WPF的邊框虛線問(wèn)題

    這篇文章主要介紹了OpenXml?Pptx的邊框虛線轉(zhuǎn)為WPF的邊框虛線,在文中用PPTX的7種直線,分別設(shè)置7種能夠設(shè)置的虛線類型,具體實(shí)例代碼跟隨小編一起看看吧
    2021-12-12
  • picturebox加載圖片的三種方法與網(wǎng)站驗(yàn)證碼的抓取

    picturebox加載圖片的三種方法與網(wǎng)站驗(yàn)證碼的抓取

    這篇文章主要介紹了picturebox加載圖片的三種方法與網(wǎng)站驗(yàn)證碼的抓取,需要的朋友可以參考下
    2015-03-03
  • C#中Class的實(shí)例化過(guò)程詳解

    C#中Class的實(shí)例化過(guò)程詳解

    文章詳細(xì)闡述了C#中類的成員,包括靜態(tài)字段、靜態(tài)構(gòu)造函數(shù)、實(shí)例字段等的初始化順序,在無(wú)繼承情況下,實(shí)例化分為聲明時(shí)初始化和構(gòu)造函數(shù)中初始化兩種,分別有明確的執(zhí)行順序,需要的朋友可以參考下
    2024-09-09
  • C#的四種基本數(shù)據(jù)類型

    C#的四種基本數(shù)據(jù)類型

    本文主要介紹了C#的四種基本數(shù)據(jù)類型的相關(guān)知識(shí),具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧
    2017-03-03
  • C# 常用不同日志庫(kù)的區(qū)別與示例解析

    C# 常用不同日志庫(kù)的區(qū)別與示例解析

    C# 作為一種流行的編程語(yǔ)言,有許多優(yōu)秀的日志庫(kù)可供選擇,本文將介紹一些常見(jiàn)的 C# 日志庫(kù),包括 NLog、log4net、Serilog 和 Microsoft.Extensions.Logging,并通過(guò)示例展示它們的使用方法及區(qū)別,感興趣的朋友一起看看吧
    2024-06-06

最新評(píng)論

清涧县| 茶陵县| 宜兰市| 阿尔山市| 永清县| 分宜县| 黄梅县| 望谟县| 安岳县| 资阳市| 盐源县| 若尔盖县| 达日县| 余庆县| 东安县| 新津县| 防城港市| 遂溪县| 眉山市| 阿城市| 宣威市| 崇阳县| 福清市| 乌拉特后旗| 绍兴市| 靖远县| 新乐市| 南昌市| 湟源县| 兰考县| 青田县| 慈利县| 兴宁市| 威海市| 尼木县| 六安市| 松原市| 临潭县| 大丰市| 辉南县| 卢龙县|