Toolbar-storming

by Bron Skinner 9. November 2010 21:53

**The Final Product

Rendered (sans propert icons and logical hierarchy):

Silverlight Toolbar

Input XML:

                         <Toolbar>
                             <ToolbarOption display='File'>
                              <Options>
                               <Option icon='icon_settings' display='New' args='string1,string2,string3' desc='[user.usertheme](syntaxresolution allowed),arg2 is this, arg3 is that' func='MyTestFunction'>
                                <Options>
                                 <Option display='Document' func='CreateNewDocument' args='txt' desc='filetype extension' >
                                                    <Options>
                                         <Option display='Text' func='CreateNewDocument' args='txt' desc='filetype extension' />
                                                        <Option display='PDF' func='CreateNewDocument' args='txt' desc='filetype extension' />
                                                        <Option display='RDL' func='CreateNewDocument' args='txt' desc='filetype extension' />
                                                        <Option display='Excel' func='CreateNewDocument' args='txt' desc='filetype extension' />
                                        </Options>
                                                <Option display='Text' func='CreateNewDocument' args='txt' desc='filetype extension' />
                                                </Option>
                                </Options>
                               </Option>
                               <Option display='Exit' args='' desc='' func='Exit' />
                              </Options>
                             </ToolbarOption>
                             <ToolbarOption display='Edit'>
                              <Options>
                                        <Option icon='icon_settings' display='Undo' args='string1,string2,string3' desc='[user.usertheme](syntaxresolution allowed),arg2 is this, arg3 is that' func='MyTestFunction' >
                                            <Options>
                                                <Option display='Bookmarks' args='' desc='' func='Exit' />
                                                <Option display='Bookmarks' args='' desc='' func='Exit' />
                                            </Options>   
                                        </Option>
                                        <Option icon='icon_settings' display='Redo' args='string1,string2,string3' desc='[user.usertheme](syntaxresolution allowed),arg2 is this, arg3 is that' func='MyTestFunction' />
                               <Option icon='icon_settings' display='Find and Replace' args='string1,string2,string3' desc='[user.usertheme](syntaxresolution allowed),arg2 is this, arg3 is that' func='MyTestFunction'>
                                <Options>
                                                <Option display='Quick Find' func='CreateNewDocument' args='txt' desc='filetype extension' />
                                 <Option display='Settings' func='CreateNewDocument' args='txt' desc='filetype extension' >
                                                    <Options>
                                         <Option display='Func1' func='CreateNewDocument' args='txt' desc='filetype extension' />
                                                        <Option display='Func2' func='CreateNewDocument' args='txt' desc='filetype extension' />
                                        </Options>
                                                </Option>
                                </Options>
                               </Option>
                              </Options>
                             </ToolbarOption>
                            </Toolbar>";

Summary:

Pretty Cool Toolbar control that lets you supply XML in contruction of option hierarchies or programmaticly build in the backend. Option clicks are interpreted in either of two ways, programmatic ToolbarOptions can subscribe to the individual events and run custom code or if ToolbarOption.Func attributes are non-null/empty, attempt to invoke a matching function on the ToolBar.Parent object. This method must contain a matching digital signature for any supplied Toolbar.Args. A String[] Array is generated from the supplied comma-delimited xml attribute value and currently only supports arguments of type String. ParentRef is set either by adding the Toolbar control to a visual tree as a child element, or by setting the property manually. The control is not fully componentized as it still highly relies on style resources and types inherit to another app I've been working on, but could be migrated to a stand alone control pretty easily. Either way, I think it's pretty cool ;) 

        /// <summary>
        /// Uses System.Reflection to attempt to invoke method name supplied on parent ToolBar.ParentRef object.
        /// Fired when option is clicked and ToolbarOption.Function is non empty/null.
        /// Passes ToolbarOption.Args to Member Invoked - method arguments must match supplied arguments and must all be typeof(string)
        /// </summary>
        /// <param name="e"></param>
        private void InvokeOptionMethod(OptionEventArgs e)
        {
            if (e != null
                && !string.IsNullOrEmpty(e.Function)
                && this.ParentRef != null)
            {
                try
                {
                    ParentRef.GetType().InvokeMember(e.Function, BindingFlags.IgnoreCase | BindingFlags.InvokeMethod, null, ParentRef, e.Args);
                }
                catch (Exception ex)
                {
                    OnToolbarException(ex);
                }
            }
        }

** End of Update

Toolbar => Collection of ToolbarHeader
  => Collection of ContextPopup

XFunction/Actions => (XML) namespace reflection invocation (cpu?)
    => (object) XAction : IXAction (string[] args, void Invoke(string[] args))
    or => XAction collection ? App.Current.Resources/Global...
   => switch(key) { case: logic; }

VisualDefinition - (XML) <id(guid)><display(string)>
MethodDefinition - Collection<KeyValuePair(guid, XAction)>
ContextPopup - UIElement Renders Menu/highlighting/calculates position of children menus

E.g.

<Toolbar>
 <ToolbarOption>
  <header>File</header>
  <Options>
   <Option> 
   <id>9365f54e-e9fd-4679-9579-91bc92d971c0</id>
   <display>New</display>
   <args>string1,string2,string3</args>
   <desc>[user.usertheme](syntaxresolution allowed),arg2 is this, arg3 is that</desc>
    <Options>
     <Option> 
     <id>9365f54e-e9fd-4679-9579-91bc92d971c2</id>
     <display>Text Document</display>
     <args>.txt</args>
     <desc>filetype</desc>
     </Option>
    </Options>
   </Option>
   <Option> 
   <id>9365f54e-e9fd-4679-9579-91bc92d971c3</id>
   <display>Exit</display>
   <args />
   <desc />
   </Option>
  </Options>
 </ToolbarOption>
 <ToolbarOption>
  <header>Edit</header>
  <Options />
 </ToolbarOption>
</Toolbar>


public class XActions
{
 public XActions(string[] args, Guid key)
 {
  try
  {

   InvokeMethod(args, key);
  }
  catch(Exception ex)
  {
   new ErrorDialog("The Squirrels have taken over..").show();
  }
 }

 public void InvokeMethod(Guid key, string[] args)
 {
  switch(key)
  {
   case ...
    ...logic
    
   break;
   case ...
   
   //desc node tells us what each indexed argument represents
   //should add some sort of validation, expected types/arg.length vs actual
   new ObjectHelper().LoadMyObject(Convert.ToInt(args[0]), args[1]);   

   break;
  }
 }


1. Option Click
2. Get Option id
3. Lookup id in MethodDefinition in global/static/instanced definition class
4. If exists, construct string[] from <args> node and passvalues to MethodDefinition instance
5. Logic happens... the squirrels attack!
 

Tags:

Technical

Powered by BlogEngine.NET 1.5.0.7
Custom theme for digitalboon.com by Bron Skinner

About the author

A Software Developer with a keen artistic sense, I’ve spent the last couple years working with predominantly Microsoft-based technologies developing web applications. The majority of this time has been spent building applications with SilverlightTM that forward some rather unique approaches to interface design. I am currently working full time.

 

 

Make sure to check out The Forge.


Download Resume