我嘗試了解一下 listboxview 與背景關系選單相結合的作業原理,因此我撰寫了以下 XAML 代碼:
<UserControl>
...
<ListView
x:Name="level1Lister"
Grid.Row="1"
behaviours:AutoScrollListViewBehaviour.ScrollOnNewItem="True"
ItemsSource="{Binding LogBuffer, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Padding" Value="1" />
<Setter Property="Margin" Value="2,0" />
<Setter Property="BorderThickness" Value="0" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<StackPanel.ContextMenu>
<ContextMenu>
<MenuItem Command="{Binding Path=DataContext.ValidateAllCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}, FallbackValue=9999999999}" Header="Copy" />
</ContextMenu>
</StackPanel.ContextMenu>
<TextBlock Foreground="{Binding Color, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Text="{Binding Message, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</UserControl>
我的主要問題是我無法訪問我的“ValidateAllCommand”函式,出于某種原因......我認為它與“RelativeSource={RelativeSource FindAncestor ...”部分有關,但我無法弄清楚如何。
uj5u.com熱心網友回復:
的“問題”ContextMenu在于它不是可視化樹的一部分。原因是MenuItem使用 aPopup來托管內容。雖然Popup本身是可視化樹的一部分,但其子內容在新Window實體中呈現時斷開連接。我們知道Window樹中只能有一個,這Window必須是根。
由于Binding.RelativeSource遍歷可視化樹,從 的分離樹內開始Popup,以查找系結源,因此Bindig無法決議。
該Popup.Child內容繼承DataContext的Popup。在 的情況下,ContextMenu這意味著從或 從 的父級MenuItem繼承,更準確地說。在您的方案是對資料模型即的。DataContextContextMenuContextMenuDataContextListBoxItemDataContextDataTemplate
這意味著,一種解決方案可能是在專案模型中實作命令。
第二種解決方案是利用路由命令。在您的場景中,此解決方案可能更合理。路由命令/事件可以跨越兩棵樹之間的邊界。
在以下示例中,我使用了ApplicationCommands.Copy命令,這是預定義的路由命令之一。將MenuItem.Parameter被系結到DataContext,這是該專案的資料模型(從繼承ContextMenu,如前所述)。這樣命令處理程式就可以知道資料源。
事件處理程式可以使用該UIElement.CommandBindings屬性附加到任何父元素。在示例中,處理程式附加到ListBox元素:
主視窗.xaml
<ListBox>
<ListBox.CommandBindings>
<CommandBinding Command="{x:Static ApplicationCommands.Copy}"
Executed="CopyCommand_Executed" />
</ListBox.CommandBindings>
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type local:DataItem}">
<StackPanel>
<StackPanel.ContextMenu>
<ContextMenu>
<!--
Here we are in a detached visual tree.
The DataContext is inherited from the ContextMenu element.
The framework allows routed events to cross the boundaries between the trees.
-->
<MenuItem Command="{x:Static ApplicationCommands.Copy}"
CommandParameter="{Binding}"
Header="Copy" />
</ContextMenu>
</StackPanel.ContextMenu>
<TextBlock />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
主視窗.xaml.cs
private void CopyCommand_Executed(object sender, ExecutedRoutedEventArgs e)
{
var listBoxItemModel = e.Parameter as LogBufferItem;
// TODO::Handle Copy command. For example:
var commandTarget = this.DataContext as ICommandModel;
commandTarget.ValidateAllCommand.Execute(listBoxItemModel);
}
第三個,但不推薦的解決方案是系結DataContext的的ContextMenu家長所關心的方面:
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type local:DataItem}">
<StackPanel>
<!-- DataTemplate DataContext -->
<Grid DataContext="{Binding RelativeSource={RelativeSource AncestorType=ListBox}, Path=DataContext}">
<!-- ListBox DataContext -->
<Grid.ContextMenu>
<ContextMenu>
<!--
Here we are in a detached visual tree.
The DataContext is inherited from the ContextMenu/Grid element.
-->
<MenuItem Command="{Binding ValidateAllCommand}"
Header="Copy" />
</ContextMenu>
</Grid.ContextMenu>
</Grid>
<!-- DataTemplate DataContext -->
<TextBlock />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/390353.html
