سؤال

لقد قمت فقط بالقليل من تطوير Flex حتى الآن، لكنني فضلت أسلوب إنشاء عناصر التحكم برمجيًا على ملفات mxml، لأن (و لو سمحت, ، صححني إذا كنت مخطئًا!) لقد أدركت أنه لا يمكنك الحصول على كلا الاتجاهين - أي أن يكون لديك وظيفة الفئة في ملف فئة ActionScript منفصل ولكن لديك العناصر المضمنة المعلنة في mxml.

لا يبدو أن هناك فرقًا كبيرًا من حيث الإنتاجية، لكن ربط البيانات برمجيًا يبدو أقل تافهًا إلى حد ما.لقد ألقيت نظرة على كيفية قيام مترجم mxml بتحويل تعبيرات ربط البيانات.والنتيجة هي مجموعة من عمليات الاسترجاعات التي تم إنشاؤها وخطوط أكثر بكثير من تمثيل mxml.إذن هذا هو السؤال: هل هناك طريقة لربط البيانات برمجياً لا تنطوي على عالم من الأذى؟

هل كانت مفيدة؟

المحلول

لا تخافوا من MXML.إنه أمر رائع لوضع وجهات النظر.إذا كتبت بنفسك قابلة لإعادة الاستخدام قد تمنحك كتابتها في ActionScript أحيانًا مزيدًا من التحكم، ولكن بالنسبة لطرق العرض غير القابلة لإعادة الاستخدام، فإن MXML أفضل بكثير.إنه أكثر إيجازًا، والارتباطات سهلة الإعداد للغاية، وما إلى ذلك.

ومع ذلك، فإن الارتباطات في ActionScript الخالص لا تحتاج إلى أن تسبب الكثير من الألم.لن يكون الأمر بهذه البساطة كما هو الحال في MXML حيث يتم تنفيذ الكثير من الأشياء لك، ولكن يمكن القيام بذلك دون بذل الكثير من الجهد.

ما لديك هو BindingUtils وأساليبها bindSetter و bindProperty.أستخدم الخيار الأول دائمًا تقريبًا، لأنني عادةً ما أرغب في القيام ببعض الأعمال أو الاتصال invalidateProperties عندما تتغير القيم، لا أرغب أبدًا في تعيين خاصية.

ما تحتاج إلى معرفته هو أن هذين يقومان بإرجاع كائن من هذا النوع ChangeWatcher, ، إذا كنت تريد إزالة الارتباط لسبب ما، فيجب عليك التمسك بهذا الكائن.وهذا ما يجعل الارتباطات اليدوية في ActionScript أقل ملاءمة من تلك الموجودة في MXML.

لنبدأ بمثال بسيط:

BindingUtils.bindSetter(nameChanged, selectedEmployee, "name");

يؤدي هذا إلى إعداد الارتباط الذي سيستدعي الطريقة nameChanged عندما name الخاصية على الكائن في المتغير selectedEmployee التغييرات.ال nameChanged ستتلقى الطريقة القيمة الجديدة لـ name الخاصية كوسيطة، لذلك يجب أن تبدو كما يلي:

private function nameChanged( newName : String ) : void 

المشكلة في هذا المثال البسيط هي أنه بمجرد إعداد هذا الربط، سيتم تنشيطه في كل مرة تتغير فيها خاصية الكائن المحدد.قيمة المتغير selectedEmployee قد يتغير، لكن الارتباط لا يزال معدًا للكائن الذي أشار إليه المتغير من قبل.

هناك طريقتان لحل هذا:إما للحفاظ على ChangeWatcher عاد بواسطة BindingUtils.bindSetter حول والاتصال unwatch عليه عندما تريد إزالة الارتباط (ثم إعداد ربط جديد بدلاً من ذلك)، أو ربطه بنفسك.سأعرض لك الخيار الأول أولاً، ثم سأشرح لك ما أعنيه بالارتباط بنفسك.

ال currentEmployee يمكن تحويله إلى زوج getter/setter وتنفيذه على النحو التالي (إظهار أداة الضبط فقط):

public function set currentEmployee( employee : Employee ) : void {
    if ( _currentEmployee != employee ) {
        if ( _currentEmployee != null ) {
            currentEmployeeNameCW.unwatch();
        }

        _currentEmployee = employee;

        if ( _currentEmployee != null ) {
            currentEmployeeNameCW = BindingUtils.bindSetter(currentEmployeeNameChanged, _currentEmployee, "name");
        }
    }
}

ما يحدث هو أنه عندما currentEmployee تم تعيين الخاصية لتبدو لمعرفة ما إذا كانت هناك قيمة سابقة، وإذا كان الأمر كذلك، فسيتم إزالة الارتباط لهذا الكائن (currentEmployeeNameCW.unwatch())، فإنه يقوم بتعيين المتغير الخاص، وما لم تكن القيمة الجديدة null يقوم بإعداد رابط جديد لـ name ملكية.والأهم من ذلك أنه يحفظ ChangeWatcher تم إرجاعها بواسطة المكالمة الملزمة.

هذا هو نمط الربط الأساسي وأعتقد أنه يعمل بشكل جيد.ومع ذلك، هناك خدعة يمكن استخدامها لجعل الأمر أسهل قليلاً.يمكنك ربط نفسك بدلا من ذلك.بدلاً من إعداد الروابط وإزالتها في كل مرة currentEmployee تغييرات الخاصية يمكنك جعل نظام الربط يقوم بذلك نيابةً عنك.في الخاص بك creationComplete المعالج (أو المنشئ أو على الأقل في وقت مبكر) يمكنك إعداد ربط مثل ذلك:

BindingUtils.bindSetter(currentEmployeeNameChanged, this, ["currentEmployee", "name"]);

يؤدي هذا إلى إنشاء ارتباط ليس فقط بـ currentEmployee الملكية على this, ، بل أيضًا إلى name الملكية على هذا الكائن.لذلك في أي وقت إما يغير الطريقة currentEmployeeNameChanged وسوف يطلق.ليست هناك حاجة لحفظ ChangeWatcher لأنه لن يلزم إزالة الارتباط أبدًا.

يعمل الحل الثاني في كثير من الحالات، لكنني وجدت أن الحل الأول يكون ضروريًا في بعض الأحيان، خاصة عند العمل مع الارتباطات في فئات غير قابلة للعرض (منذ this يجب أن يكون مرسل الحدث و currentEmployee يجب أن تكون قابلة للربط حتى تعمل).

نصائح أخرى

وهي موجودة اعتبارا من اليوم.:)

لقد قمت للتو بإصدار مشروع ربط بيانات ActionScript كمصدر مفتوح: http://code.google.com/p/bindage-tools

BindageTools هو بديل لـ BindingUtils (انظر اللعب على الكلمات هناك؟) يستخدم واجهة برمجة التطبيقات (API) بطلاقة حيث تعلن عن ربط البيانات الخاصة بك في نمط خط الأنابيب:

Bind.fromProperty(person, "firstName")
    .toProperty(firstNameInput, "text");

الارتباطات ذات الاتجاهين:

Bind.twoWay(
    Bind.fromProperty(person, "firstName"),
    Bind.fromProperty(firstNameInput, "text"));

تحويل البيانات الصريحة والتحقق من صحتها:

Bind.twoWay(
    Bind.fromProperty(person, "age")
        .convert(valueToString()),
    Bind.fromProperty(ageInput, "text")
        .validate(isNumeric()) // (Hamcrest-as3 matcher)
        .convert(toNumber()));

إلخ.هناك الكثير من الأمثلة على الموقع.هناك الكثير من الميزات الأخرى أيضًا، تعال وألق نظرة.--ماثيو

يحرر:واجهات برمجة التطبيقات المحدثة

تتمثل إحدى طرق فصل MXML وActionScript لمكون ما في ملفات منفصلة في القيام بشيء مشابه لرمز ASP.Net 1.x الموجود خلف النموذج.في هذا النموذج، يعد الجزء التعريفي (MXML في هذه الحالة) فئة فرعية من الجزء الأمري (ActionScript).لذلك قد أعلن عن الكود الموجود خلف فصل مثل هذا:

package CustomComponents
{
    import mx.containers.*;
    import mx.controls.*;
    import flash.events.Event;

    public class MyCanvasCode extends Canvas
    {
        public var myLabel : Label;

        protected function onInitialize(event : Event):void
        {
            MyLabel.text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit.";
        }
    }
}

.. والترميز مثل هذا:

<?xml version="1.0" encoding="utf-8"?>
<MyCanvasCode xmlns="CustomComponents.*" 
    xmlns:mx="http://www.adobe.com/2006/mxml"
    initialize="onInitialize(event)">
    <mx:Label id="myLabel"/>    
</MyCanvasCode>

كما ترون من هذا المثال، من عيوب هذا النهج هو أنه يجب عليك الإعلان عن عناصر التحكم مثل myLabel في كلا الملفين.

هناك طريقة أستخدمها عادةً لاستخدام mxml والبرنامج النصي للعمل معًا:ترث جميع مكونات mxml الخاصة بي من فئة البرنامج النصي للإجراء حيث أقوم بإضافة كود أكثر تعقيدًا.ثم يمكنك الرجوع إلى مستمعي الأحداث المطبقين في هذه الفئة في ملف mxml.

يعتبر،

روث

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top