国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

[XAML]類似WPF綁定的Binding的讀取方法

2019-11-17 02:29:59
字體:
來源:轉載
供稿:網友

[XAML]類似WPF綁定的Binding的讀取方法

在WPF的XAML里,依賴屬性可以使用基于BindingBase之類的MarkupExtensin

讀取XAML時,會自動的把該BindingBase轉換為BindingExPRessionBase

然后再放入DependencyObject的EffectiveValueEntry里

那么問題來了,在我們自己做一個輕量級依賴框架時,為什么讀取BindingBase會報錯

假設,一個屬性名稱為Title,類型為string

XAML文檔為

<Page xmlns="http://schemas.wodsoft.com/web/presentation"      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"      Title="{Binding Content, ElementName=source}">    <ContentControl Name="source" Content="Test"/></Page>

在該輕量級框架里

Binding和WPF的一樣

在ProvideValue方法執行時,同樣會返回BindingExpression

如果讀取該XAML,則會報錯

類型“Wodsoft.Web.Data.BindingExpression”的對象無法轉換為類型“System.String”。

因為XAML讀取器會使用CLR來賦值,即使用Title屬性的Setter來賦值

顯然,BindingExpression無法給Title直接賦值

那么WPF是如何辦到的呢?

也許你用過WPF的XamlReader,位于System.Windows.Markup下

該類的靜態方法Load能讀取XAML內容

同樣也能正確讀取Binding等MarkupExtension

該方法核心用到XamlXmlReader與XamlObjectWriter

一個讀取XAML內容,一個把XAML內容變成Object

我們現在就要通過這兩個類實現我們的需求

首先實現一個ObjectReader

public class ObjectReader{    public static object Load(Stream stream)    {        XamlXmlReader reader = new XamlXmlReader(stream);        XamlObjectWriter writer = new ObjectWriter();        while (reader.Read())        {            writer.WriteNode(reader);        }        writer.Close();        return writer.Result;    }}

XamlXmlReader就用原本的Reader

它負責讀取XAML文檔內容

我們要寫一個ObjectWriter,繼承自XamlObjectWriter

在里面實現我們的依賴系統

public class ObjectWriter : XamlObjectWriter{    public ObjectWriter() : base(new XamlSchemaContext()) { } object _Instance; protected override void OnBeforeProperties(object value) { _Instance = value; base.OnBeforeProperties(value); }    //設置屬性值    protected override bool OnSetValue(object eventSender, XamlMember member, object value)    {        if (eventSender is DependencyObject)        {            //獲取依賴屬性            DependencyProperty dp = DependencyProperty.FromName(member.Name, member.DeclaringType.UnderlyingType);            if (dp == null)            {                //如果不是依賴屬性,則使用CLR方法賦值                return base.OnSetValue(eventSender, member, value);            }            DependencyObject target = (DependencyObject)eventSender;            //使用自己框架的SetValue方法賦值            target.SetValue(dp, value);            return true;        }        else            return base.OnSetValue(eventSender, member, value);    }    //寫入成員方法    public override void WriteStartMember(XamlMember property)    {        //判斷是否是依賴類型        if (property.DeclaringType != null && property.DeclaringType.UnderlyingType.IsSubclassOf(typeof(DependencyObject)))        {            //如果是屬性            if (property.UnderlyingMember is PropertyInfo)            {                //防止目標類型未調用靜態構造函數                //這里我不知道還有什么方法可以引發類型的靜態構造函數                if (_Instance == null)                    _Instance = Activator.CreateInstance(property.DeclaringType.UnderlyingType);                //獲取依賴屬性                DependencyProperty dp = DependencyProperty.FromName(property.Name, property.DeclaringType.UnderlyingType);                if (dp != null)                {                    //如果是依賴屬性                    //覆蓋XamlMember                    //使用我們自己MemberInvoker                    property = new XamlMember((PropertyInfo)property.UnderlyingMember, SchemaContext, new ObjectMemberInvoker(dp));                }            }        }        base.WriteStartMember(property);    }    private object _Instance;    private bool _IsDependencyObject;}

OnSetValue方法是設置普通值類型的屬性時用到的

WriteStartMember則是當非值類型屬性時調用到

這里需要編寫一個ObjectMemberInvoker,繼承自XamlMemberInvoker

我們需要重寫GetValue和SetValue方法

這樣我們就能達到我們的目標了

public class ObjectMemberInvoker : XamlMemberInvoker{    public ObjectMemberInvoker(DependencyProperty property)    {        Property = property;    }    public DependencyProperty Property { get; private set; }    public override object GetValue(object instance)    {        DependencyObject d = (DependencyObject)instance;        return d.GetValue(Property);    }    public override void SetValue(object instance, object value)    {        DependencyObject d = (DependencyObject)instance;        if (value is BindingExpression)        {            //...        }        else            d.SetValue(Property, value);    }}

在SetValue方法里判斷value

如果是綁定類則調用相關方法

否則調用依賴屬性的設置方法

現在我們就能正常讀取綁定而不會報錯了

結束語

XAML很強大,可以擴展出很多東西

但是里面有很多東西微軟是沒有開放的

拿來做框架會遇到很多坑

甚至于沒有解決方法

更多出現于VS的XAML編輯器里

比如這個問題

http://stackoverflow.com/questions/18671317/each-dictionary-entry-must-have-an-associated-key

這個BUG已經有人報告給VS團隊并通過了

但至今未解決&hellip;…


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 徐州市| 石台县| 华安县| 攀枝花市| 英德市| 葫芦岛市| 鄂尔多斯市| 台北县| 武隆县| 浦北县| 和顺县| 巴马| 方正县| 永顺县| 五寨县| 黑山县| 资溪县| 桦南县| 广州市| 义马市| 芮城县| 安泽县| 通海县| 吴旗县| 临武县| 纳雍县| 东方市| 运城市| 武冈市| 墨江| 汽车| 樟树市| 盐津县| 青川县| 永昌县| 张家界市| 临西县| 潼南县| 固始县| 汶川县| 吉安市|