WPF ContextMenu没有看到用户控件的依赖属性

时间:2017-04-17 17:41:14

标签: c# wpf data-binding contextmenu caliburn.micro

我有一个带有一些文本框的用户控件(名为mUserControl),其内容受限于类(模型)的属性,名为Module。用户控件本身具有一个Module类型的自定义依赖属性(ItemSource)。所以我可以将文本框的内容绑定到Module的属性。

此用户控件是更大视图(HomeScreenView)的一部分。我可以从HomeScreenViewmodel轻松访问ItemsSource。一切正常,除了文本框上的ContextMenu。我收到了绑定错误。 ContextMenu没有看到用户控件的ItemsSource属性,而所有其他元素都这样做。我知道,ContextMenu在不同的可视化树上。我尝试过不同的方法来完成这项工作,却没有成功。欢迎任何建议!

UserControl xaml(为简洁起见而简化):

<UserControl x:Class="xxx.Views.ModuleFrameView"
x:Name="mUserControl">
<Grid>
<TextBox x:Name="txt5" Text="{Binding ItemSource.Ch1SET, 
ElementName=mUserControl}" IsEnabled="{Binding ItemSource.IsEnbl_5, 
ElementName=mUserControl}" IsReadOnly="True"                        
TextAlignment="Center" ContextMenuService.ShowOnDisabled="True"
Tag="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}">
<TextBox.ContextMenu >
     <ContextMenu Name="cm">
             <MenuItem Header="Enable" cal:Message.Attach="cmEnable($source)" IsCheckable="True" IsChecked="
{Binding Path=PlacementTarget.Tag.DataContext.ItemSource.IsEnbl_5, 
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=TextBox}}"/>
     </ContextMenu>
</TextBox.ContextMenu>
<!--...-->

ModuleFrameView在代码隐藏文件中定义了ItemSource属性:

public Module ItemSource
    {
        get { return (Module)GetValue(ItemSourceProperty); }
        set { SetValue(ItemSourceProperty, value); }
    }

    public static readonly DependencyProperty ItemSourceProperty =
    DependencyProperty.Register("ItemSource", typeof(Module), typeof(ModuleFrameView), new PropertyMetadata(default(Module)));

此类型的DP模块:

public class Module : PropertyChangedBase
{
    private string _ch1SET;
    public string Ch1SET
    {
        get { return _ch1SET; }
        set
        {
            if (_ch1SET == value) return;
            _ch1SET = value;
            NotifyOfPropertyChange(() => Ch1SET);
        }
    }
private bool _isEnbl_5;
    public bool IsEnbl_5
    {
        get { return _isEnbl_5; }
        set
        {
            if (_isEnbl_5 == value) return;
            _isEnbl_5 = value;
            NotifyOfPropertyChange(() => IsEnbl_5);
        }
    }
//...
//...lot of properties

第二个用户控件(上面提到的更大的视图)&#39; xaml:

<UserControl x:Class="xxx.Views.HomeScreenView">
<Grid>
    <ContentControl>
<loc:ModuleFrameView Grid.Row="0" Grid.Column="0" ItemSource="{Binding ModuleArr[0]}"/>
<loc:ModuleFrameView Grid.Row="0" Grid.Column="1" ItemSource="{Binding ModuleArr[1]}"/>
<!--...-->

2 个答案:

答案 0 :(得分:0)

有点拿铁但是如果你的datacontext设置正确,你不需要名字,你可以简化如下(未经测试)但DP可以直接访问+“ItemSource”是错误的属性名称,如果你只有一个元素=&GT;改为“CurrentModule”

<UserControl x:Class="xxx.Views.ModuleFrameView">
    <Grid x:Name="ROOT">
       <TextBox Text="{Binding CurrentModule.Ch1SET}" IsEnabled="{Binding CurrentModule.IsEnbl_5}" IsReadOnly="True"                        
TextAlignment="Center" ContextMenuService.ShowOnDisabled="True">
<TextBox.ContextMenu >
     <ContextMenu>
         <MenuItem Header="Enable" cal:Message.Attach="cmEnable($source)" IsCheckable="True" IsChecked="{Binding Path=CurrentModule.IsEnbl_5, ElementName="ROOT"}"/>
     </ContextMenu>
</TextBox.ContextMenu>

除此之外,您的HomeScreenView需要被绑定到模块集合的列表替换,并为您的loc定义项目模板:ModuleFrameView with“List ItemSource =”{Binding ModuleArr}“

答案 1 :(得分:0)

PlacementTarget是父ContextMenu的属性,因此您应使用ContextMenu作为AncestorType而不是TextBox

<MenuItem Header="Enable" cal:Message.Attach="cmEnable($source)" IsCheckable="True" 
          IsChecked="{Binding Path=PlacementTarget.Tag.DataContext.ItemSource.IsEnbl_5, 
            RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}"/>