Search code examples
wpfmvvmdata-bindingmergeuser-controls

How to Merge user controls that Binds to SAME obj smoothly?


I'm trying to merge some user controls that are binded to same target. At the start, it looks simple but I have no idea with this how can I deliver binding target to daughter control (controls inside merge control)?

I want to make this:

    <Canvas>
        <local:Teeth x:Name="sideR" Points="{Binding Points[0]}" IsClosedCurve="{Binding IsClosedCurve}"/>
        <local:WrapTeeth Points="{Binding Points[0]}"/>
        <ListBox ItemsSource="{Binding Points[0]}" ItemContainerStyle="{StaticResource PointListBoxItemStyle}">
            <ListBox.Template>
                <ControlTemplate>
                    <Canvas IsItemsHost="True"/>
                </ControlTemplate>
            </ListBox.Template>
        </ListBox>
    </Canvas>

into

    <local:MergeControl Points="{Binding Points[0]}"/>

Solution

  • Your UserControl should have a Points dependency property like shown below. It is not clear from your question whether you need a more specialized collection type than IEnumerable. Possibly replace it with PointCollection or something more suitable.

    public partial class MergeControl : UserControl
    {
        public static readonly DependencyProperty PointsProperty = DependencyProperty.Register(
            "Points", typeof(IEnumerable), typeof(MergeControl));
    
        public IEnumerable Points
        {
            get { return (IEnumerable)GetValue(PointsProperty); }
            set { SetValue(PointsProperty, value); }
        }
    
        public MergeControl()
        {
            InitializeComponent();
        }
    }
    

    The elements in the UserControl's XAML would bind to this property by RelativeSource Bindings. You may need to define another property for the IsClosedCurve Binding of the Teeth element.

    <UserControl ...>
        <UserControl.Resources>
            <Style x:Key="PointListBoxItemStyle" TargetType="ListBoxItem">
                ...
            </Style>
        </UserControl.Resources>
        <Canvas>
            <local:Teeth x:Name="sideR"
                Points="{Binding Points, RelativeSource={RelativeSource AncestorType=UserControl}}"
                IsClosedCurve="{Binding IsClosedCurve, ...}"/>
    
            <local:WrapTeeth
                Points="{Binding Points, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
    
            <ListBox
                ItemsSource="{Binding Points, RelativeSource={RelativeSource AncestorType=UserControl}}"
                ItemContainerStyle="{StaticResource PointListBoxItemStyle}">
                <ListBox.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas/>
                    </ItemsPanelTemplate>
                </ListBox.ItemsPanel>
            </ListBox>
        </Canvas>
    </UserControl>
    

    Note also that ItemsControls have an ItemsPanel property to set the Panel element that is used to contain their items.