Search code examples
wpfdata-bindingtelerik

WPF - Binding data template


I'm trying to bind <DataTemplate> on Telerik RadDiagram ShapeStyle:

<telerik:RadDiagram x:Name="Diagram"
                            ShapeStyle="{StaticResource NodeStyle}"
                            GraphSource="{Binding GraphSource}"/>

This style looks like this:

    <Grid.Resources>
        <Style x:Key="NodeStyle" TargetType="telerik:RadDiagramShape">
            <Setter Property="Position" Value="{Binding Position, Mode=TwoWay}" />
            <Setter Property="Content" Value="{Binding}" />
            <Setter Property="Geometry" Value="{telerik:CommonShape ShapeType=RectangleShape}" />
            <Setter Property="ContentTemplate" >
                <Setter.Value>
                    <MultiBinding Converter="{StaticResource StyleConverter}">
                        <Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=UserControl}"/>
                        <Binding Path=""/>
                    </MultiBinding>
                </Setter.Value>
            </Setter>
        </Style>
...
</Grid.Resources>

StyleConverter:

class StyleConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        FrameworkElement targetElement = values[0] as FrameworkElement;

        if (values[0] is BilledMsisdnViewModel)
            return targetElement.FindResource("BilledMsisdnControl");
        else if(values[0] is BilledImeiViewModel)
            return targetElement.FindResource("ImeiControl");

        return null;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Those resources (BilledMsisdnControl and ImeiControl) are defined in <UserControl.Resources>:

<UserControl.Resources>
    <ResourceDictionary>
        <local:BilledMsisdnControl x:Key="BilledMsisdnControl"/>
        <local:ImeiControl x:Key="ImeiControl"/>
        <local:StyleConverter x:Key="StyleConverter"/>
    </ResourceDictionary>
</UserControl.Resources>

And they are created by me user controls.

So my goal here is according to binded view model type select user controll (this part works) and then use it as ContentTemplate (this don't work). I'm getting just object namespace nad name for ImeiControl or BilledMsisdnControl in diagram node. enter image description here

How can I fix this?


Solution

  • According to the documentation you should use style selector

    public class NodeStyleSelector : StyleSelector 
    { 
        public Style BilledMsisdnStyle { get; set; } 
        public Style BilledImeiStyle { get; set; } 
     
        public override Style SelectStyle(object item, DependencyObject container) 
        { 
            if (item is BilledMsisdnViewModel) 
                return BilledMsisdnStyle; 
            else if (item is BilledImeiViewModel) 
                return BilledImeiStyle; 
            else return base.SelectStyle(item, container); 
        } 
    }
    

    Define styles with ContentTemplate. Inside ContentTemplate add your user controls.

    <Style x:Key="BilledMsisdnStyle" TargetType="telerik:RadDiagramShape">
        <Setter Property="Position" Value="{Binding Position, Mode=TwoWay}" />
        <Setter Property="Content" Value="{Binding}" />
        <Setter Property="Geometry" Value="{telerik:CommonShape ShapeType=RectangleShape}" />
        <Setter Property="ContentTemplate" >
            <Setter.Value> 
                <DataTemplate> 
                    <local:BilledMsisdnControl/> 
                </DataTemplate> 
            </Setter.Value> 
        </Setter>
    </Style>
    
    
    <Style x:Key="BilledImeiStyle" TargetType="telerik:RadDiagramShape">
        <Setter Property="Position" Value="{Binding Position, Mode=TwoWay}" />
        <Setter Property="Content" Value="{Binding}" />
        <Setter Property="Geometry" Value="{telerik:CommonShape ShapeType=RectangleShape}" />
        <Setter Property="ContentTemplate" >
            <Setter.Value> 
                <DataTemplate> 
                    <local:ImeiControl/> 
                </DataTemplate> 
            </Setter.Value> 
        </Setter>
    </Style>
    

    Add shape style selector

    <styleselectors:NodeStyleSelector x:Key="CustomShapeStyleSelector" 
                    BilledMsisdnStyle="{StaticResource BilledMsisdnStyle}" 
                    BilledImeiStyle="{StaticResource BilledImeiStyle}" /> 
    

    Use ShapeStyleSelector for your RadDiagram.

    <telerik:RadDiagram x:Name="Diagram"
                            ShapeStyleSelector="{StaticResource CustomShapeStyleSelecto}"
                            GraphSource="{Binding GraphSource}"/>