这是我的应用程序的布局草图:
<UserControl>
<Grid>
<Grid.ColumnDefinitions>...</Grid.ColumnDefinitions>
<Grid.RowDefinitions>...</Grid.RowDefinitions>
<Border>...</Border>
<Grid>...</Grid>
<DataGrid Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="2" AutoGenerateColumns="False"
HorizontalAlignment="Stretch" Name="myDataGrid" VerticalAlignment="Stretch"
ItemsSource="{Binding Path=MyModel.Files}"
SelectedItem="{Binding SelectedFile}"
Margin="0,0,10,3" CanUserReorderColumns="False" CanUserResizeRows="False" Style="{StaticResource DataGridStyle_Generic}"
IsReadOnly="True">...</DataGrid.ContextMenu>
</DataGrid>
<Border>...</Border>
<Border BorderBrush="Gray" BorderThickness="1" Grid.Row="4" Grid.Column="1" Grid.ColumnSpan="2" Margin="0,0,10,0">
<Grid Margin="0,0,10,0">
<Grid.ColumnDefinitions>...</Grid.ColumnDefinitions>
<Grid.RowDefinitions>...</Grid.RowDefinitions>
<StackPanel Grid.Row="1" Orientation="Horizontal" Margin="0,0,10,2">
<Button>...</Button>
<Button Margin="0" Name="m_DropDownButton" Padding="0, 4"
HorizontalAlignment="Center" VerticalAlignment="Center"
ContextMenuService.IsEnabled="False" Click="m_DropDownButton_Click">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
<Path x:Name="BtnArrow" Margin="4" VerticalAlignment="Center" Width="6" Fill="#FF000000" Stretch="Uniform" HorizontalAlignment="Right" Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z "/>
</StackPanel>
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="All files" Command="{Binding AllFilesCommand}" />
<MenuItem Header="Selected files only"
Command="{Binding SelectedFilesOnlyCommand}"
CommandParameter="{Binding Path=SelectedItems, ElementName=myDataGrid}"/>
</ContextMenu>
</Button.ContextMenu>
</Button>
</StackPanel>
<StackPanel Grid.Row="0" Orientation="Horizontal" VerticalAlignment="Stretch" Margin="0,0,10,0">...</StackPanel>
</Grid>
</Border>
</Grid>
</UserControl>
我想将myDataGrid
的SelectedItems
属性作为myMenuItem
的命令中的CommandParameter传递。我怎样才能做到这一点?
注意#1:这两个控件位于Visual Tree的远处,它们的第一个公共父控件是myGrid
。找不到任何有效的解决方案,因为我总是在输出窗口中收到"找不到绑定的源"错误消息。
注意#2:DataGrid的SelectedItems
属性是只读的,因此不允许将其绑定到ViewModel属性。
注意#3:我希望避免任何代码背后的代码,例如为DataGrid的SelectionChanged
事件创建事件处理程序。
我没有尝试Sheridan的方式,值得一读。
无论如何,你也可以尝试以下破解:
<Button Margin="0" Name="m_DropDownButton" Padding="0, 4"
HorizontalAlignment="Center" VerticalAlignment="Center"
ContextMenuService.IsEnabled="False" Click="m_DropDownButton_Click"
Tag="{Binding ElementName=myDataGrid}"
>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
<Path x:Name="BtnArrow" Margin="4" VerticalAlignment="Center" Width="6" Fill="#FF000000" Stretch="Uniform" HorizontalAlignment="Right" Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z "/>
</StackPanel>
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="All files" Command="{Binding AllFilesCommand}" />
<MenuItem Header="Selected files only"
Command="{Binding SelectedFilesOnlyCommand}"
CommandParameter="{Binding Path=PlacementTarget.Tag.SelectedItems, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}}"/>
</ContextMenu>
</Button.ContextMenu>
</Button>
注意按钮上的"Tag"属性和CommandParameter绑定。
后面还有一个小代码,但我相信你也有:
private void m_DropDownButton_Click(object sender, RoutedEventArgs e)
{
var button = (Button)sender;
button.ContextMenu.PlacementTarget = button;
button.ContextMenu.IsOpen = true;
}
让我知道。
您有一个棘手的需求需要满足,但有解决方案。这有点长,可能也有点痛苦,因为你还有相当多的工作要做,但就在这里。
因为ContextMenu
不是普通视觉树的一部分,所以它无法访问在那里定义的元素或DataContext
的成员。要解决这个问题,需要做两(或三)件事。第一件事是向视图模型中添加一个属性,以便将数据绑定到DataGrid.SelectedItems
属性。
您必须做的第二件事是创建一种在DataGrid.SelectedItems
属性上具有TwoWay Binding
的方法,因为"内置"属性是只读的。幸运的是,网上有很多关于这个主题的帖子,涉及到自定义可绑定SelectedItems
附加属性的使用。我想你可以自己找到它们。
因此,现在假设您有权访问视图模型中的选定项或代码隐藏,接下来需要将ContextMenu.DataContext
属性设置为视图模型的实例。我们可以使用ContextMenu.PlacementTarget
性质和一直有用的Tag
性质来做到这一点。。。试试这个:
<Button Tag="{Binding DataContext, RelativeSource={RelativeSource AncestorType={x:Type
Views:YourView}}}">
<Button.ContextMenu>
<ContextMenu DataContext="{Binding PlacementTarget.Tag, RelativeSource={
RelativeSource Self}}">
<MenuItem />
<MenuItem Name="myMenuItem" Command="{Binding DoAction}"
CommandParameter="{Binding SelectedItems}" />
</ContextMenu>
</Button.ContextMenu>
</Button>
Tag
属性中的Binding
将看起来绑定到父视图(Window
或UserControl
)的DataContext
属性的内容,假设它的名称为YourView
,并且您已经为视图项目或文件夹设置了名为Views
的XML命名空间前缀。
接下来,ContextMenu.DataContext
从Tag
属性设置为相同的值,因此现在ContextMenu
可以访问SelectedItems
属性和视图模型中的命令。