結果 我弄清楚了自己發生了什么。我有一種奇怪的組合,所以這對其他人可能有用也可能沒有用。
我將繼續在答案條目中記錄解決方案。我的解決方案涉及少量代碼隱藏。我通常不喜歡代碼隱藏。它只是與視圖相關的,所以不會破壞 MVVM。如果有人給我一個不太遠的僅 XAML 解決方案,我很樂意將其用作接受的答案。
問題
我有一個 WPF 應用程式 (.NET6),它有一個影像網格,代表離散物件。我希望每個人都有一個相同的背景關系選單。每個人都需要發送一個唯一的CommandParameter,以便視圖模型可以識別要操作的物件。
為了給自己一種添加識別符號的方法,我將 Button 子類化如下:
public class PartButton : Button
{
public int PartPosition { get; set; }
}
我知道有關背景關系選單不在可視樹中的問題,因此沒有DataContext從頂級控制元件繼承(UserControl在這種情況下)。訣竅通常只是用來PlacementTarget獲取父級,并使用它的DataContext.
讓左鍵單擊和右鍵單擊一樣作業也是一個目標。為此,我在按鈕上使用了一個RoutedEventforClick并使用了一個toStoryboard設定。如果您對 XAML 更有經驗,您可能已經看到了問題。ContextMenu.IsOpentrue
因為有 30 個按鈕,最終目標是通過一種樣式添加選單,以便可以使用盡可能少的代碼宣告按鈕。為了讓一個作業正常,我這樣嘗試:
<jb:PartButton
Grid.Row="2" Grid.Column="2"
IsEnabled="{ Binding Path=PartStatuses[1] }"
PartPosition="1">
<Image Source="../Resources/Part.png" />
<jb:PartButton.ContextMenu>
<ContextMenu DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Test Part"
CommandParameter="{Binding Path=PartPosition}"
Command="{Binding Source={StaticResource Proxy}, Path=Data.TestPartCmd}"
/>
</ContextMenu>
</jb:PartButton.ContextMenu>
</jb:PartButton>
這適用于右鍵單擊。但是,當使用RoutedEvent上面的技巧時,左鍵單擊結果PlacementTarget總是null.
uj5u.com熱心網友回復:
<ContextMenu>
<MenuItem Header="Test Part" CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self}}" Command="{Binding TestPartCmd}"/>
</ContextMenu>
和這樣的 ViewModel
public RelayCommand<System.Windows.Controls.MenuItem> TestPartCmd
{
get
{
return new RelayCommand<System.Windows.Controls.MenuItem>((menuItem) =>
{
int partPosition = ((PartButton)((System.Windows.Controls.Primitives.Popup)((System.Windows.FrameworkElement)menuItem.Parent).Parent).PlacementTarget).PartPosition;
});
}
}
可能有更好的方法,但我還沒有想到。
uj5u.com熱心網友回復:
正如所承諾的,這是我目前的解決方案:
<ContextMenu>
<MenuItem Header="Bootloader Test"
CommandParameter="{Binding Path=PlacementTarget.PartPosition, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
Command="{Binding Path=PlacementTarget.DataContext.BootloaderTestCmd, RelativeSource={RelativeSource AncestorType=ContextMenu}}"
/>
為了作業,它需要這個代碼隱藏:
public void OnPartButtonPressed(object sender, RoutedEventArgs e)
{
if (sender is Button btn)
{
btn.ContextMenu.PlacementTarget = btn;
btn.ContextMenu.IsOpen = true;
}
}
就目前而言,這現在已完全實作為一種樣式,因此每個按鈕真正需要的一切都是這樣的:
<jb:PartButton
PartPosition="1"
Grid.Row="2" Grid.Column="2" />
在實際專案中,我還為物件上的按鈕宣告了影像,因為我很難通過樣式來完成它。影像取決于PartPosition必須在視圖模型中決議的索引 ()。很難使用必須從物件中查詢的值來使用樣式從視圖模型中獲取屬性。但是,不同的問題,以及我以后可能會或可能不會擔心的事情。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/443433.html
