如何正确绑定 sub-usercontrol 依赖项 属性 的共享 属性

How to properly bind a shared property of a sub-usercontrol dependency property

我有 4 个不同的 collection。目前我显示这 4 collection 个,但我当时只能选择一个元素。

我显示 4 的视图 collection:

<UserControl x:Class="xxx.yyy.vvv.Menu"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:xxx.yyy.vvv.Menu"
             mc:Ignorable="d" 
             d:DesignHeight="800" d:DesignWidth="450">
    <Grid  Name="RootContainer">
        <Grid.DataContext>
            <local:MenuViewModel/>
        </Grid.DataContext>
        <ItemsControl ItemsSource="{Binding Collection}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <local:CollectionControl Collection="{Binding}" SelectedElement="{Binding Path=DataContext.GlobalSelectedElement,ElementName=RootContainer, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Vertical" />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>
    </Grid>
</UserControl>

这已绑定到 ViewModel:

public class MenuViewModel : SomeBaseViewModelThatHandleTheNotify
{
    public IMyElement GlobalSelectedElement
    {
        get => GetValue<IMyElement>();
        set => SetValue(value); //I NEVER COME HERE!!!)
    }
    public SomeCollectionContainer Collection
    {
        get => GetValue<SomeCollectionContainer>();
        set => SetValue(value);
    }
}

我的子控件有一个依赖项 属性,它会在 UserControl 的内部 ViewModel 更改时更改。

    public IMyElement SelectedElement
    {
        get { return (IMyElement)GetValue(SelectedElementProperty); }
        set { SetValue(SelectedElementProperty, value);/*HERE I COME!*/ }
    }
    public static readonly DependencyProperty SelectedElementProperty =
        DependencyProperty.Register("SelectedElement", typeof(IMyElement), typeof(CollectionControl), new PropertyMetadata(null, OnSelectedElementChanged));

    private static void OnSelectedElementChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
    {
        //Retrieve the sub control ViewModel and set the property
        SubControlViewModel subControlViewModel = (SubControlViewModel)((CollectionControl)dependencyObject).RootContainer.DataContext;
        subControlViewModel.SelectedElement = (IMyElement)dependencyPropertyChangedEventArgs.NewValue;
    }

    //In the constructor, I register to PropertyChanged of the ViewModel, and I set the SelectedElement when it change.

所以,基本上,我进入了 UserControl 的依赖项 属性 的 SetValue,但我从来没有进入我的主 ViewModel 的 GlobalSelectedElement 属性。

我错过了什么?

编辑 我尝试直接在我的 ViewModel 和依赖项 属性 之间使用 two-way 绑定,也不起作用:

在我的子控件中:

<UserControl x:Class="xxx.yyy.vvv.CollectionControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:xxx.yyy.vvv.Menu"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <StackPanel Name="RootContainer" Orientation="Vertical">
        <StackPanel.DataContext>
            <local:CollectionControlViewModel/>
        </StackPanel.DataContext>
        <Label Content="{Binding Collection.Name}" Margin="5,0,0,0" />
        <ListBox ItemsSource="{Binding Collection.Items}" HorizontalContentAlignment="Stretch" Padding="0" BorderThickness="0" SelectedItem="{Binding SelectedElement, RelativeSource={RelativeSource AncestorType={x:Type local:CollectionControl}}, Mode=TwoWay}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    ...
                </DataTemplate>
            </ListBox.ItemTemplate>
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Vertical" />
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
        </ListBox>
    </StackPanel>
</UserControl>

我觉得我的 UserControl Dependency属性 是从两个方面绑定的

我试着画了一张小图来展示我的 类。 所以我的 CollectionControl.SelectedElement 设置正确,但 MenuViewModel.SelectedItem 设置不正确。

尝试使用 RelativeSource:

绑定到父 ItemsControlDataContext
<local:CollectionControl Collection="{Binding}" 
                         SelectedElement="{Binding Path=DataContext.GlobalSelectedElement, RelativeSource={RelativeSource AncestorType=ItemsControl}, Mode=TwoWay}"/>

显然使用 ElementName 是行不通的。这是因为 namescopesItemTemplate 中的 CollectionControl 元素与 "RootContainer" 不在同一个名称范围内。