下午好,
我有一个似乎很常见的问题。我有一个用户控件,它有一个视图模型作为其数据上下文。用户控件中的元素,然后将此ViewModel用于绑定目的,等等。
ViewModel
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将这些注释呈现给票证显示用户控件。
<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。当然,简单地使用;
<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),并且都产生了类似于;
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')或
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}没有什么区别?
发布于 2011-03-08 18:28:02
ContextMenus实际上不是WPF VisualTree的一部分,所以绑定不能像预期的那样工作。作为另一种选择,尝试这种绑定:
<MenuItem Header="Spam" Command="{Binding PlacementTarget.DataContext.HideSelectedText,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}" />发布于 2014-04-28 11:10:40
最好的解决方案是通过资源来实现。如果ContextMenu将在资源中创建,它将自动从父源继承DataContext。那么,创建一个具有静态资源传递值的样式就是一件简单的事情。
示例:
<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上进行了测试,但我认为它也适用于早期版本。
https://stackoverflow.com/questions/5236212
复制相似问题