2

I'm using XAML to set a style for objects of type "LayoutAnchorableItem". This class contains a property "Model" of type object. I would like to convert this to type IVisible in XAML using an IValueConverter:

public class LayoutAnchorableItem
{
  object Model { get; }
  // .. other properties & methods ..
}


public interface IVisible
{
  bool isVisible { get; set; }
  // .. other properties ..
}

public class ObjectToIVisibleConverter : IValueConverter
{
  // ...
  // "Converts" LayoutAnchorableItem.Model to IVisible by looking up the model's reference in an internal dictionary
}

Then, I would like to use the resulting IVisible-object and databind its isVisible-property to my style setters:

<ad:DockingManager.LayoutItemContainerStyleSelector>
    <view:PanesStyleSelector>
        <view:PanesStyleSelector.ToolStyle>
            <Style TargetType="{x:Type ad:LayoutAnchorableItem}">

        <!-- PSEUDO-CODE! I cant use {Binding ...} inside a {Binding ...} -->
                <Setter Property="Visibility" Value="{Binding {Binding Model, Converter={StaticResource ObjectToIVisibleConverter}}.isVisible, Converter={StaticResource BoolToVisibilityConverter}}"/>

            </Style>
        </view:PanesStyleSelector.ToolStyle>
    </view:PanesStyleSelector>
</ad:DockingManager.LayoutItemContainerStyleSelector>

But how can I do this in XAML?

I've only ever seen examples of how IValueConverters convert complex objects to basic types (string, double etc.) - but can I also use it to convert an object to another object of different type, and then bind to one of its properties?

Otherwise, is there any other way do to this? I've thought about including another , but that didn't work out either (plus changing the entire element's DataContext may not be very smart...).


As for why I'm doing this: This is a style settler for an AvalonDock Element. My view models don't contain any AvalonDock-specific properties (such as isVisible) though, so I need to store them seperately, e.g. in a Dictionary< object, IExtendedLayoutInformation >. For databinding, I'm trying to convert the viewmodel (LayoutAnchorableItem.Model) to IExtendedLayoutInformation by looking it up in my dictionary, and then need to bind to the fields of this IExtendedLayoutInformation object.

Bogey
  • 4,926
  • 4
  • 32
  • 57
  • Why not directly convert to `Visibility` instead of `IVisible`? The converter could be what your IVisible implementation does. – Clemens Dec 09 '14 at 09:44
  • Thanks - Problem is, there are many extended properties, not just isVisible - so I'd need to create converters for each (a bit annoying). Plus, could imagine that might cause problems for two-way bindings - e.g. can't just convert a bool back to the approrpriate IExtendedLayoutInformation object without finding a way to store and pass on additional information (such as a reference to the view model) – Bogey Dec 09 '14 at 09:50

1 Answers1

2

You can set your inner binding to another property, like DataContext, Tag, or a custom attached property, and have your outer binding bind to it. For example:

<Setter Property="Tag"
        Value="{Binding Model, Converter={StaticResource ObjectToIVisibleConverter}}"/>
<Setter Property="Visibility"
        Value="{Binding Tag.isVisible, RelativeSource={RelativeSource Self}, Converter={StaticResource BoolToVisibilityConverter}}"/>

Another way would be to use a chained converter - something like the ones mentioned in this question: Is there a way to chain multiple value converters in XAML?

Community
  • 1
  • 1
Adi Lester
  • 24,731
  • 12
  • 95
  • 110
  • Thanks a TON Adi! I've been dealing with this issue for days.. Your solution works excellently, and the code is really clean & easy to read too.. couldn't be any better! Cheers – Bogey Dec 09 '14 at 10:35
  • Actually, the only issue I'm facing with this is that "Visibility" doesn't change when the underlying object (Tag.isVisisble) changes. Or rather: All changes feed through nicely when I'm binding directly to Tag.isVisible, but changes do not feed through anymory once I apply the BoolToVisibilityConverter to it. This is odd.. in case you can spontaneously think of a reason, appreciate another input of course! Will keep researching myself – Bogey Dec 09 '14 at 12:32
  • Try making `BoolToVisibilityConverter` a MultiValueConverter and bind both `Tag` and `Tag.isVisible` to it. – Adi Lester Dec 09 '14 at 13:06
  • For testing, I've now exposed isVisible directly of type "Visibility" to avoid conversion. This all works fine when I'm binding it to e.g. the (string) "Title" property, exposed by AvalonDock's LayoutAnchorableItem (inherited by its LayoutItem) class. But it doesn't update with changes when binding to the "Visibility"-property of the same class (inherited by LayoutItem - FrameworkElement - UIElement). And yet, works fine again when bound to Visibility property of a plain Label's style in an ItemsControl. Have to research more, don't get what's happening here at all... – Bogey Dec 09 '14 at 15:01