zoukankan      html  css  js  c++  java
  • Silverlight.FX & Silverlight Behaviors

    http://projects.nikhilk.net/SilverlightFX
    http://www.nikhilk.net/Silverlight-Behaviors.aspx

    Silverlight Behaviors

    A framework for creating reusable and attachable behaviors in Silverlight, and a sample behavior that demonstrates using and building them... along with all the code.

    In the past, I've written about behaviors and control extenders in the context of Ajax and HTML-based UI. This post introduces a similar behavior semantics for Silverlight and XAML-based UI as well.

    The mini-behavior framework I have prototyped allows you to write and use behavior as a combination of a component + an attached property. The framework provides the logic to attach/detach behaviors for behavior authors. The rest of this post demonstrates using and writing a simple behavior based on this framework. Over the next few posts, I'll discuss a few more behaviors as a way to further experiment and demonstrate the behavior concept.

    Using the DefaultCommit Behavior
    Lets say you're implementing a typical form with a TextBox and a search Button. You'll probably want to allow users to press the Enter key after typing in some search keywords to kick off the search rather than force them to click the button explicitly. What you'd normally do is write a couple of event handlers to handle both the Click event from the Button and the KeyDown event from the TextBox (to look for the Enter key) in your code-behind, and trigger the search logic from each of them. This is more complicated and messy than it needs to be.

    Ideally you simply want to handle a single event - the button's Click event. In fact, in HTML forms, this is built in into the notion of a Form with a submit button. However, it isn't so in Silverlight, where a Form concept is baked in. This is where this behavior comes in. Once this behavior is available, I can author the following XAML:

    <TextBox x:Name="searchTextBox">
      <f:Form.Commit>
        <f:DefaultCommit ButtonName="searchButton" />
      </f:Form.Commit>
    </TextBox>
    <f:Button x:Name="searchButton" Content="Search"
      Click="OnSearchButtonClick" />
    

    Essentially the DefaultCommit behavior is attached to the TextBox using the XAML syntax above. For those new to XAML and Silverlight, f:Form.Commit refers to the Commit attached property offered by the Form class. This is similar to Canvas.Left, which you've probably encountered. The only difference is that the type of the Canvas.Left attached property is a simple double value, whereas the type of the Form.Commit property is a DefaultCommit.

    Underneath the covers, the DefaultCommit behavior does the same thing you'd do in code-behind, but does so in a way that the logic is now encapsulated and is easily reusable. You can instantiate as many of these as you want, especially across multiple forms/pages without duplicating the event handling logic all over.

    You might have noticed the use of <f:Button> instead of a regular Button. Unfortunately, unlike WinForms and HTML buttons, the Silverlight Button control currently doesn't have any way to programmatically invoke the Click event, so I had to add that functionality in a derived class.

    Implementing the DefaultCommit Behavior
    The behavior framework I have put together introduces two classes Behavior and BehaviorManager.

    The first step is to implement a behavior by deriving from the Behavior class. The Behavior class is a generic class, to allow indicating the type of objects that behavior can be associated with.

    public class DefaultCommit : Behavior<TextBox> {
    }
    

    The next step is to add any properties exposed by the behavior itself.

    public class DefaultCommit : Behavior<TextBox> {
    
        private string _buttonName;
        
        public string ButtonName {
            get { return _buttonName; }
            set { _buttonName = value; }
        }
    }
    

    The behavior base class holds the reference to the associated object as its AssociatedObject property. It defines a couple of abstract methods to manage the lifetime of a behavior instance: OnAttach, and OnDetach. The derived behavior class implements these to perform associated logic, such as setup and cleanup including subscribing and unsubscribing to events raised by the associated object.

    public class DefaultCommit : Behavior<TextBox> {
    
        protected override void OnAttach() {
            AssociatedObject.KeyDown += OnTextBoxKeyDown;
        }
        
        protected override void OnDetach() {
            AssociatedObject.KeyDown -= OnTextBoxKeyDown;
        }
        
        private void OnTextBoxKeyDown(object sender, KeyEventArgs e) {
            if ((e.Key == Key.Enter) && (AssociatedObject.Text.Length != 0)) {
                Button button = AssociatedObject.FindName(_buttonName) as Button;
                if (button != null) {
                    button.PerformClick();
                }
            }
        }
    }
    

    The final step is to define an attached property that can be used to declaratively create an instance of this behavior and have it be associated with a TextBox. This is where the BehaviorManager class will come into play. It provides a set of utility methods that correctly attach/detach behaviors.

    public static class Form {
    
        public static readonly DependencyProperty CommitProperty =
            DependencyProperty.RegisterAttached("Commit", typeof(Form), typeof(DefaultCommit),
                OnCommitPropertyChanged);
        
        public static DefaultCommit GetCommit(TextBox textBox) {
            return BehaviorManager.GetBehavior<DefaultCommit>(textBox);
        }
        
        public static void SetCommit(TextBox textBox, DefaultCommit commitBehavior) {
            BehaviorManager.SetBehavior(textBox, commitBehavior);
        }
        
        private void OnCommitPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) {
            BehaviorManager.UpdateBehavior(o, CommitProperty,
                                           (DefaultCommit)e.OldValue,
                                           (DefaultCommit)e.NewValue);
        }
    }
    

    There you go... writing a basic behavior is quite straightforward.

    Concepts and Next Steps
    One rough analogy to behaviors is that of extension methods in C# 3.0. Those are at the method level. Behaviors are similar, but are live components. More specifically, a behavior is a component that encapsulates some functionality and can be attached to another component to extend its built-in functionality, without creating a derived class. A couple of example behaviors that can be attached to a TextBox besides the one implemented above include auto-complete and input filtering.

    The fact that behaviors are attached components that implies a composition-like metaphor, offers two advantages whenever derivation is non-essential:

    • Allows "extending" multiple component types - in the TextBox example, the behaviors can be attached not only to TextBox but also to WatermarkTextBox.
    • A single TextBox can be associated with multiple behaviors as needed, rather than requiring the developer to build and use a kitchen-sink style control that has to anticipate every possible feature.

    Almost all behaviors handle events and encapsulate a set of event handlers into a reusable component that can then be instanced declaratively. Often this leads to a more declarative style of programming (something I love) and reduced code-behind clutter.

    I chose a simple behavior scenario to introduce the concept. In a future post, I'll demonstrate some more interesting behaviors, including AutoComplete , and some animation scenarios. Stay tuned. Over time, I'll continue to experiment with this. I have some ideas on implementing declarative views that are enabled via this concept.

    I'd love to hear ideas you might have for behaviors that would be useful additions for Silverlight and XAML-based UI, and especially for RIA scenarios.

    You can also download the code which contains the behavior framework, the sample behavior, and a sample app that makes use of them.


    [ Tags: silverlight | xaml | prototype ]
  • 相关阅读:
    JAVA语言 第五周
    JAVA语言 第四周
    Good Bye 2016 D. New Year and Fireworks BFS
    Codeforces Round #402 (Div. 2) D. String Game 二分
    Codeforces Round #401 (Div. 2) E. Hanoi Factory 栈
    Good Bye 2016 C. New Year and Rating 模拟
    Codeforces Round #147 (Div. 2) C. Primes on Interval 二分
    Codeforces Round #398 (Div. 2) B. The Queue 思维
    Divide by Zero 2017 and Codeforces Round #399 (Div. 1 + Div. 2, combined) D. Jon and Orbs 概率DP
    Divide by Zero 2017 and Codeforces Round #399 (Div. 1 + Div. 2, combined) E. Game of Stones Nim游戏
  • 原文地址:https://www.cnblogs.com/ueqtxu/p/1538291.html
Copyright © 2011-2022 走看看