首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ItemsControl - FindAncestor中的WPF绑定无法工作

ItemsControl - FindAncestor中的WPF绑定无法工作
EN

Stack Overflow用户
提问于 2011-03-08 17:43:02
回答 2查看 5.6K关注 0票数 0

下午好,

我有一个似乎很常见的问题。我有一个用户控件,它有一个视图模型作为其数据上下文。用户控件中的元素,然后将此ViewModel用于绑定目的,等等。

ViewModel

代码语言:javascript
复制
public class TicketDetailsViewModel : ViewModelBase
{
    public DelegateCommand<object> HideSelectedText { get; private set; }

    private Ticket _ticket;
    public Ticket Ticket
    {
        get { return _ticket; }
        set
        {
            _ticket = value;
            this.RaisePropertyChanged(p => p.Ticket);
        }
    }
}

我的ViewModel包含一个票据对象。此票证对象具有附加到它的注释集合,并使用ItemsControl将这些注释呈现给票证显示用户控件。

代码语言:javascript
复制
 <ItemsControl ItemsSource="{Binding Path=Ticket.Comments}">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <Border CornerRadius="15" Background="{Binding Path=CommentType, ConverterParameter=CommentType, Converter={StaticResource ResourceKey=commentColorConverter}}" Padding="10" Margin="40,10,40,0">
                                <TextBox x:Name="tbComment" Text="{Binding CommentText}" IsReadOnly="True">
                                <TextBox.ContextMenu>
                                    <ContextMenu>
                                        <MenuItem Header="Spam" Command="{Binding Path=DataContext.HideSelectedText,RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type UserControl} }}">

                                        </MenuItem>
                                    </ContextMenu>
                                </TextBox.ContextMenu>
                            </TextBox>
                        </Border>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>  
                            <StackPanel Orientation="Vertical"/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                </ItemsControl>  

您将注意到这个ItemsControl呈现的每个ItemsControl都附加了一个ContextMenu。我要做的是将这个ContextMenuItem的命令绑定到我的ViewModel中的DelegateCommand。当然,简单地使用;

代码语言:javascript
复制
<MenuItem Header="Spam" Command="{Binding HideSelectedText}">

我们没有得到任何有用的东西,因为在这个上下文中‘绑定’等于一个Ticket.Comment,因此不知道HideSelectedText实际上是什么。

似乎有许多类似于问题,所有的答案似乎都转向了RelativeSource解决方案。正如您在我的原始XAML代码中所看到的,我已经尝试过这一点,并且尝试过许多其他版本(有和没有AncestorLevel集,有AncestorType={x:Type ItemsControl},AncestorType={x:Type ItemsControl},AncestorType={x:Type DataTemplate} ect),并且都产生了类似于;

代码语言:javascript
复制
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.UserControl', AncestorLevel='1''. BindingExpression:Path=DataContext.HideSelectedText; DataItem=null; target element is 'MenuItem' (Name=''); target property is 'Command' (type 'ICommand')

代码语言:javascript
复制
System.Windows.Data Error: 40 : BindingExpression path error: 'HideSelectedText' property not found on 'object' ''TicketComment' (HashCode=49290260)'. BindingExpression:Path=DataContext.HideSelectedText; DataItem='ContextMenu' (Name=''); target element is 'MenuItem' (Name=''); target property is 'Command' (type 'ICommand')

那么,为什么这个解决方案似乎适用于这么多人,但对我来说,只键入{Binding HideSelectedText}没有什么区别?

EN

回答 2

Stack Overflow用户

发布于 2011-03-08 18:28:02

ContextMenus实际上不是WPF VisualTree的一部分,所以绑定不能像预期的那样工作。作为另一种选择,尝试这种绑定:

代码语言:javascript
复制
<MenuItem Header="Spam" Command="{Binding PlacementTarget.DataContext.HideSelectedText,
    RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}" />
票数 3
EN

Stack Overflow用户

发布于 2014-04-28 11:10:40

最好的解决方案是通过资源来实现。如果ContextMenu将在资源中创建,它将自动从父源继承DataContext。那么,创建一个具有静态资源传递值的样式就是一件简单的事情。

示例:

代码语言:javascript
复制
<DataGrid.Resources>
    <ContextMenu x:Key="test_ContextMenu" DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}">
        <MenuItem Header="Test Header" Command="{Binding Path=TestCommand, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
    </ContextMenu>
</DataGrid.Resources>

<DataGrid.ItemContainerStyle>
    <Style TargetType="DataGridRow">
        <Setter Property="ContextMenu" Value="{StaticResource test_ContextMenu}"/>
    </Style>
</DataGrid.ItemContainerStyle>

这段代码在.NET 4.5上进行了测试,但我认为它也适用于早期版本。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5236212

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档