views:

257

answers:

2

I'm working on a set of controls that has a number of DependencyProperties. The properties are themselves DependencyObjects and created during the get method of the properties. During the Get method, they are also set back to the propertybag using the SetValue() method, so they are in fact valid in Xaml and their properties can be storyboarded without having to explicitly created in the the visual tree.

These DependencyObjects has all its properties as DependencyProperties as well, for supporting DataBinding. They are as mentioned above possible to use in Storyboards.

At the same time I'm developing special designtime support for Blend 3 for these properties and have created an InlineEditorTemplate in the form of a Control. I create the template and set it for the PropertyValueEditor like this:

  var vectorEditControl = new FrameworkElementFactory(typeof (VectorEditorControl));
  var dataTemplate = new DataTemplate {VisualTree = vectorEditControl};
  InlineEditorTemplate = dataTemplate;

In the Control I have the following:

<Grid DataContext="{Binding Value}">

<StackPanel Orientation="Horizontal">
  <TextBox Text="{Binding Path=X, Mode=TwoWay}"/>
    <TextBox Text="{Binding Path=Y, Mode=TwoWay}"/>
    <TextBox Text="{Binding Path=Z, Mode=TwoWay}"/>
</StackPanel>

</Grid>

The editor shows up and I can edit the data. And even while debugging, I see that it actually sets the data back to the DependencyProperties on the DependencyObjects, but nothing happens to the Xaml. So the data is actually not persisted in any way in the Xaml and lost when I close the Xaml file and open it again.

Is there anything I need to do specifically for it to actually get into the Xaml? I was under the impression that this would happen automatically?

+1  A: 

Hi Einar,

Excellent Question!

The core issue you're running into a misunderstanding as to what PropertyEditors in Blend/Cider end up databinding to.

Consider this object graph:
- MyControl
-- MyControl.MyProperty
--- FooClass
---- FooClass.BarProperty

Let's look at a scenario where we have a PropertyEditor (of any type: Inline, Dialog or Extended) to property MyControl.MyProperty. When inside MyPropertyPropertyEditor you'd expect to get a fully settable copy of FooClass and be able to manipulate it's members. That's a good assumption, but the wrong one.

The core issue is that Blend/Cider have elaborate data structures that represent your model at design time. There's about 3-5 levels of abstraction in how Blend/Cider interact with an actual control.
Creating those levels of abstraction allows Expression Blend / Visual Studio designers to be leveraged between framewroks (Silverlight / WPF) and support advanced scenarios (like Property transactions and property chaining).

So, the value you actually get to DataBind to is just one of those levels of abstraction.
Don't believe me? In your custom PropertyEditor, register for this.DataContextChanged event and checkout the type in this.DataContext. You'll end up getting the PropertyValue class (or one of it's friends).

Every single property change you want persisted to XAML (and shown on the design surface) should go through those abstraction layers.

the question you have to ask yourself is "Where do I get one of these absteaction classes for my PropertyValue.Value property instance?".

Well, what I'd do if I were you is create a ModelItem around MyControl.MyProperty and set that as your PropertyEditor.DataContext. We've shipped an example of using ModelFactory.CreateItem in the Silverlight Toolkit as part of the Chart DefaultInitializer: Source Code, Ning Zhang (Awesome Design Time Dev) explains about ModelItem

If you've got follow-up questions I'd consider pinging PeteBl or UnniR through the Silverlight Insiders mailing list.

Sincerely,
-- Justin

JustinAngel
Thanks this is excellent.Now I don't have to bang my head against the wall tonight.
Einar Ingebrigtsen
A: 

It partly solves my problem. I'm having a dialog with UnniR for a followup. I couldn't see how I could use this together with the PropertyValueEditor, but for default values this is brilliant and something I'll implement ASAP.

Thanks.

Einar Ingebrigtsen