[XAML] similar to the Binding read method bound to WPF, xamlwpf

Source: Internet
Author: User

[XAML] similar to the Binding read method bound to WPF, xamlwpf

In the XAML of WPF, you can use MarkupExtensin Based on BindingBase.

When reading XAML, The BindingBase is automatically converted to BindingExpressionBase.

Then, put it in the DependencyObject's inclutivevalueentry.

 

The problem is: Why does an error occur when we read BindingBase when we build a lightweight dependency framework?

Assume that an attribute is named Title and its type is string.

The XAML document is

<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>

In this lightweight framework

The same for Binding and WPF

When the ProvideValue method is executed, the BindingExpression will also be returned.

If you read this XAML, an error is returned.

Objects of the type "Wodsoft. Web. Data. BindingExpression" cannot be converted to the type "System. String ".

This is because the XAML reader uses CLR to assign values, that is, the Setter of the Title attribute is used to assign values.

Obviously, BindingExpression cannot directly assign values to the Title.

 

So how does WPF do it?

You may have used XamlReader of WPF, which is located in System. Windows. Markup.

The static method Load of this class can read The XAML content

You can also read MarkupExtension such as Binding correctly.

The core of this method is XamlXmlReader and XamlObjectWriter.

One reads The XAML content, and the other converts the XAML content into an Object.

 

We need to implement our needs through these two classes now

First, implement an 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 uses the original Reader

It is responsible for reading the content of the XAML document.

We want to write an ObjectWriter that inherits from XamlObjectWriter.

Implement our dependency system in it

Public class ObjectWriter: XamlObjectWriter {public ObjectWriter (): base (new XamlSchemaContext () {}// protected override void OnBeforeProperties (object value) {_ Instance = value; // record whether the dependency type is _ IsDependencyObject = typeof (DependencyObject ). isAssignableFrom (_ Instance. getType (); base. onBeforeProperties (value);} // set the attribute value // only the value type can call protected override bool OnSetValue (object eventSender, Xaml Member member, object value) {if (_ IsDependencyObject) {// gets the dependency attribute DependencyProperty dp = DependencyProperty. fromName (member. name, member. declaringType. underlyingType); if (dp = null) {// if it is not a dependency attribute, use the CLR method to assign a value to return base. onSetValue (eventSender, member, value);} DependencyObject target = (DependencyObject) _ Instance; // use the SetValue method of your own framework to assign a value to target. setValue (dp, value); return true;} else return base. OnSetValue (eventSender, member, value);} // write the member method public override void WriteStartMember (XamlMember property) {// determine whether the dependency type is if (property. DeclaringType! = Null & property. declaringType. underlyingType. isSubclassOf (typeof (DependencyObject) {// if it is a property if (property. underlyingMember is PropertyInfo) {// prevents the target type from calling the static constructor. // here I don't know how to raise the type of static constructor if (_ Instance = null) _ Instance = Activator. createInstance (property. declaringType. underlyingType); // obtain the Dependency Property DependencyProperty dp = DependencyProperty. fromName (property. name, property. declaringType. underlyin GType); if (dp! = Null) {// if it is a dependency attribute // overwrite XamlMember // use our own MemberInvoker property = new XamlMember (PropertyInfo) property. underlyingMember, SchemaContext, new ObjectMemberInvoker (dp) ;}} base. writeStartMember (property);} private object _ Instance; private bool _ IsDependencyObject ;}

The OnSetValue method is used to set attributes of the common value type.

WriteStartMember is called when a non-value type attribute is used.

Here we need to write an ObjectMemberInvoker that inherits from XamlMemberInvoker

We need to override the GetValue and SetValue methods.

In this way, we can achieve our goal.

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);    }}

Judge value in SetValue Method

If it is a bound class, call the relevant method

Otherwise, call the setting method of the dependency attribute.

 

Now we can normally read the binding without reporting an error.

 

Conclusion

The XAML is very powerful and can be extended into many things.

But there are a lot of things that Microsoft is not open.

There will be a lot of pitfalls in the framework.

Even no solution

More in VS's XAML Editor

For example

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

This BUG has been reported to VS team and passed

But not yet solved ......

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.