关于c#:绑定到UserControl XAML中的依赖项属性

Binding to a Dependency Property inside UserControl XAML

我想重用控件,但是其中一种情况需要上下文菜单,而其他情况则不需要。这是我的尝试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public partial class RP8Grid : UserControl {

    public bool UseContextMenu {
        get { return (bool)GetValue(UseContextMenuProperty); }
        set { SetValue(UseContextMenuProperty, value); }
    }

    // Using a DependencyProperty as the backing store for UseContextMenu.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty UseContextMenuProperty =
        DependencyProperty.Register("UseContextMenu", typeof(bool), typeof(RP8Grid), new PropertyMetadata(false));

        public RP8Grid() {
            InitializeComponent();
        }
    }

并在XAML中使用属性:

1
<ctls:RP8Grid UseContextMenu="False"/>

现在我无法摆正的部分,如何访问UserControl中的UseContextMenu?
我尝试了以下方法:

1
2
3
4
5
<DataGrid>
  <DataGrid.ContextMenu>
    <ContextMenu IsEnabled="{Binding UseContextMenu,RelativeSource={RelativeSource AncestorType=UserControl, Mode=FindAncestor}}">
  </DataGrid.ContextMenu>
</DataGrid>

结果:

Cannot find source for binding with reference 'RelativeSource
FindAncestor, AncestorType='System.Windows.Controls.UserControl',
AncestorLevel='1'


将打开一个禁用的ContextMenu,但其项目被禁用。然后很难关闭它。如果那是您想要的(我怀疑),那么绑定代理将带您到达那里(请参阅下面该方法的完整版本)。

如果您想要的只是偶尔摆脱ContextMenu,这将起作用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<DataGrid
    >
    <DataGrid.Style>
        <Style TargetType="DataGrid" BasedOn="{StaticResource {x:Type DataGrid}}">
            <Style.Triggers>
                <DataTrigger
                    Binding="{Binding UseContextMenu, RelativeSource={RelativeSource AncestorType=UserControl}}"
                    Value="True"
                    >
                    <Setter Property="ContextMenu">
                        <Setter.Value>
                            <ContextMenu
                                >
                                <MenuItem Header="Test Item" />
                                <MenuItem Header="Test Item" />
                                <MenuItem Header="Test Item" />
                                <MenuItem Header="Test Item" />
                            </ContextMenu>
                        </Setter.Value>
                    </Setter>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </DataGrid.Style>
</DataGrid>

这是绑定代理版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class BindingProxy : Freezable
{
    #region Overrides of Freezable

    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }

    #endregion

    public object Data
    {
        get { return (object)GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Data.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty DataProperty =
        DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
}

XAML:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<DataGrid
    >
    <DataGrid.Resources>
        <local:BindingProxy
            x:Key="UserControlBindingProxy"
            Data="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}"
            />
    </DataGrid.Resources>
    <DataGrid.ContextMenu>
        <ContextMenu
            IsEnabled="{Binding Data.UseContextMenu, Source={StaticResource UserControlBindingProxy}}"
            >
            <MenuItem Header="Test Item" />
            <MenuItem Header="Test Item" />
            <MenuItem Header="Test Item" />
            <MenuItem Header="Test Item" />
        </ContextMenu>
    </DataGrid.ContextMenu>
</DataGrid>