WPF中 ContextMenu 尋找父物體的一種方案

簡亦發表於2023-12-28

據瞭解 ContextMenu 在WPF中實際是以類似於WIndow的呈現方式,所以 ContextMenu 在當前頁面的 Visualtree 中是找不到的。
當在Listbox中需要傳遞當前選中項給ContextMenu時,需要以特殊手法傳遞。

前臺XAML程式碼
 <Grid>
     <Grid.RowDefinitions>
         <RowDefinition />
         <RowDefinition Height="auto" />
     </Grid.RowDefinitions>
     <Grid.ContextMenu>
         <ContextMenu>
             <MenuItem Command="{Binding Data.DeleteFileCommand, Source={StaticResource proxy}}" Header="Delete" />
             <MenuItem Command="{Binding RenameFileCommand}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Parent.PlacementTarget}" Header="Rename" />
             <!--  {Binding ElementName=listbox} cannot find  -->
             <MenuItem Command="{Binding OpenFilePathCommand}" Header="Open File Path" />
         </ContextMenu>
     </Grid.ContextMenu>
</Grid>

在這裡透過指定ElementName的方式並不生效,因為這兩個不在同一Visualtree下,雖然寫的時候不報錯,但是執行後就會報錯。(在新版MAUI上寫的時候就會報錯)

RelativeSource的用法如下:RelativeSource

MenuItem 透過 RelativeSource 繫結到自身的父物體中的PlacementTarget屬性(注意此時並沒有程式碼提示可以自動完成),然後在後臺就可以透過Command的引數接受前臺父物體,此處演示為Grid物件;

後臺C#程式碼

 [RelayCommand]
 private void RenameFile(object obj)
 {
     var parent = obj as Grid;
     var txb = parent.FindName("txb1") as TextBox;
     if (txb != null)
     {
         IsEditFileName = true;
         txb.LostFocus += Txb_LostFocus;
         var res = txb.Focus();
     }
 }

完整示例可參考
https://github.com/KleinPan/One

相關文章