I'll admit that, though I'm familiar with WPF, I'm not an expert and have never developed an application with it. I have used Flex however, which also compiles markup to classes. So, in Flex, I might create a file named TabSettingsGeneral.mxml. The root element of this file might be a <VBox>. This means that VBox will be the base class for the generated class, whose name will be TabSettingsGeneral. The MXML compiler will insert code to call the initialize() method on the generated class, so you can wire up event listeners, etc. I imagine that this is similar to InitializeComponent() in XAML.
You could do something similar in BXML by using a BoxPane with orientation="vertical" as the root element. However, since BXML isn't compiled, this file won't be tied to any code. So, you need to create a class that extends BoxPane and use that as your root element: <my:MyBoxPane>. This class will generally implement Bindable, which provides the initialize() method that you can use to perform your initialization, similar to XAML and MXML. Does this help? On Dec 3, 2010, at 9:34 PM, Greg Brown wrote: >> If you create a class Foo that extends Component, you can use it in BXML >> just like any other component >> >> True, if Foo is defined solely in Java. > > What I meant is that it doesn't have to be a subclass of Container (though it > often probably will be). I was just trying to convey that you don't *need* to > create an intermediary element if your use case doesn't call for it. > >> But that's not what I'm talking about. I want to create components using >> bxml with Java behind them. Which, if one reads the various tutorials and >> your replies to other messages, seems to be what you think, too. > > Yes. :-) > >> And you can only use that kind of component in someone else's BXML via the >> include construct. It would be cool if that weren't so. Suppose there were >> another entry into the bxmlserializer that I could call from my constructor >> to say "make my content be the stuff you find in the following bxml file" >> (which at least conceptually is what happens in the InitializeComponent call >> in every xaml-based class in WPF). > > Sort of. A XAML file gets compiled to a class instance, and > InitializeComponent() is likely called by some glue code generated by the > compiler. It's not exactly the same as deserializing BXML in a constructor. > In BXML, the root element is instantiated by BXMLSerializer, not the new > operator. > >> I'm puzzled that you're not following me. I must really be thinking of UI >> construction very differently than you. So I'll take a stab at the concrete >> example you ask for. >> >> Here's an example of the "making it manageable" situation that comes up >> periodically for me. An app has a settings dialog, with a bunch of tabs >> devoted to different categories of settings. You could create a monster >> bxml file whose main portion looks like this: >> >> <TabPane ...> >> <TablePane bxml:id="tabGeneral" TabPane.tabData="General"> >> ... lots of stuff ... >> </TablePane> >> <Form bxml:id="tabContact" TabPane.tabData="Contact Info"> >> ... other stuff ... >> </Form> >> <Panel bxml:id="tabCreative" TabPane.tabData="Go Wild"> >> ... silly stuff ... >> </Panel> >> ... more tabs ... >> </TabPane> >> >> and have a huge pile of code in the settings dialog class to initialize the >> fields and later process them when the user clicks OK. >> >> But to make it manageable, especially if different people are responsible >> for each category, I'd much rather have the main dialog look like >> >> <TabPane ...> >> <my:TabSettingsGeneral /> >> <my:TabSettingsContact /> >> <my:TabSettingsCreative /> >> ... >> </TabPane> >> >> Then I'd take that big blob of bxml from the first tab and put it into >> TabSettingsGeneral.bxml, and put the code responsible for initializing it >> and processing it into TabSettingsGeneral.java. And similarly for the other >> tabs. >> >> Of course, I can't quite do it that way, for the reasons described in my >> first paragraph, so in the current Pivot I settle for >> >> <TabPane ...> >> <bxml:include src="TabSettingsGeneral.bxml" /> >> <bxml:include src="TabSettingsContact.bxml" /> >> <bxml:include src="TabSettingsCreative.bxml" /> >> ... >> </TabPane> >> >> And, of course TabSettingsGeneral.bxml has to be wrapped in my new Java >> class so that it will create the class: >> >> <my:TabSettingsGeneral ...> >> ... the actual blob from above ... >> </my:TabSettingsGeneral> >> >> Am I being any clearer yet? > > Yes, but I'm still not sure what the actual problem is. I think your question > is, what class should you use as the base class for TabSettingsGeneral. Is > that correct? If so, the answer is whatever layout container is most > appropriate for that part of your UI. TablePane is pretty common for TabPane > content, but of course you can use any Component. > >> By the way, in the reorganization I described above I left out the setting >> of TabPane.tabData for each component. I can't put it in >> TabSettingsGeneral.bxml, because the serializer apparently doesn't know it's >> inside a TabPane at that point. So I was pleased but rather surprised to >> find that the following works: >> >> <bxml:include src="TabSettingsGeneral.bxml" TabPane.tabData="General"/> >> >> What else can you put in an include element? > > You can basically use any property of the class corresponding to the root > element of the include. For example, if your include contained a Label, you > could do this: > > <bxml:include src="my_label.bxml" text="Hello World"/> > > A <bxml:include> is essentially the equivalent of the new operator. You are > instantiating an object based on the template defined in the BXML file. >
